Skip to content

[Announcement] [Gdscript] Godot 4.x Client Work in Progress #13719

Open
@Goutte

Description

@Goutte

Hello !

I started experimenting with a Godot client (GDScript), and albeit there's not much to show right now I wanted to write something here in case anyone else is interested in joining forces. I looked here for the keywords Godot and GDScript.

Here's the working branch.

Rationale

Being able to quickly draw a pure GDScript client for any OAS would be amazing for some online games, even though Godot has its own network engine, because in HTML5 exports only the HTTP client is available (for now). Anyway, there's plenty of uses for HTTP connections to a server in games (auth, leaderboards, news, etc.).

I don't know if GDScript will have all the features we need, we'll see along the way.

Y U NO C ?

Having to compile Godot itself and distribute it to all collaborators is no small task.
And I'd rather not have Mono if I can help it.

Design

Some ideas, constraints inherent to Godot, etc. Nothing is frozen yet.

Indent using Tabs

Godot uses tabs by default, although it is configurable.

Java code should be indented like the other generators.

Try not to pollute global space (with class_name) ?

Godot does not have namespaces. (for now)

What should we add in the global namespace (via class_name, or perhaps singleton nodes) ?

If we do decide to use class_name (and pollute global space) for models and api, which I suspect we'll need to get nice type defs, we need to set up for all class names a prefix that will act as a namespace.

We can rather easily do this for models with --model-name-prefix, just need to make sure our users know about it. I found --api-name-suffix but no prefix, although it is used in toApiName(). Probably because of lack of support across targets ? Should I add my own --api-name-prefix CLI option or wait ?

snake_case vs camelCase

I'd love some configuration but I won't bother with it until at least I have a working client.

Static typing

Godot does not allow nullable types (we're waiting for them).

This means we either skip types, or try to figure out how to replace null by the appropriate pseudo-null value for the given type. ("" for String, etc.)
But it becomes awkward for int values, where 0 might not be a sensible pseudo-null.

Async

In HTML5 exports, only async is available.
Since it is my personal target, I'll favor it.

Godot 4 has Callables and lambda defs, but no Promises yet.
I think the best method signature for our generated async API method endpoints would be to return a Promise.
But if we start waiting on the promises of Godot… ;)

Therefore, for the first major version of the generator, we'll use Callables in that fashion, unless you have a better idea :

func createUser(
	# … ← generated params from the endpoint schema
	on_success: Callable,  # func(result: User)
	on_failure: Callable  # func(error: ApiError)
):
	pass  # ← method implementation

This function signature is actually very cumbersome to use (see the current state of the demo in samples), because we'll often need to chain requests. We need to find an implementation of Promise in pure GDScript, and fast.

To Singleton or not to Singleton

I tried to avoid using Singletons (aka. Autoloads), so XxxxApi classes are simple RefCounted (plain ol' Godot Object with garbage collection), but that means each XxxxApi holds its own (host, port) configuration to lazily create its client when none was provided. Same goes for extra headers the user wants to send.

You can create the configuration once and pass it to each API class.


State of Things

I managed to bootstrap the gdscript target, compile and generate the petstore sample.
Now we need to fill the templates with working code, one feature at a time.

  • Models template basic bones
  • Apis template basic bones
  • Basic Java CodeGen
  • Enums
  • Datetimes ← using String, shifting timezone responsibility on user
  • Model Collections ← using Arrays with dubious recursion support
  • Reserved Words ← mostly done, never done
  • Configure enabled/disabled features
  • Demo / Integration Tests
  • Normalization
  • Serialization (JSON)
  • Model validation of required
  • Model validation of constraints (length, etc.)
  • Deserialization (JSON) ← my focus
  • Deserialization (JSON+LD)skipped (ouch)
  • Serialization (XML)skipped
  • Deserialization (XML)skipped
  • RequestBodies Components
  • SecuritySchemes ← hmm
  • Response Errors ← may skip
  • Unit Tests
  • Header customization
  • Single host configuration from OAS
  • Multiple host configuration from OAS
  • HTTPClient async constraint
  • HTTPClient reuse through Apis
  • Override endpoints for easier template overriding (perhaps via template partials?)
  • Bunch of configuration (YAML)
  • Bunch of configuration (CLI)

Probably won't do everything on this list myself. Will do enough for my own use, hopefully.

I'm looking at the other language targets and throwing darts. Wish me luck !

Burning questions

  1. Is there somewhere a docker image (or whatever) for a server with a working petstore I can use for my demo during dev ?

    Yes → https://github.com/OpenAPITools/openapi-generator/wiki/Integration-Tests (thanks @wing328)

  2. Should I use handlebars straight away or keep using mustache, as mildly recommended ? I'm used to (and fond of) jinja2 and Twig (Pebble, for Java).

    Moved to handlebars because the truthy value of mustache includes "" and "null" and that does not play well with {{#example}}.

  3. I made a small python script to grab the reserved keywords from Godot's XML. Since it might be useful again when updating the generator to account for changes in Godot, I'd like to keep it close. Where can I store it ? (right now it's in modules/openapi-generator/src/main/resources/gdscript, schmoozing with the templates)

Metadata

Metadata

Assignees

No one assigned

    Labels

    AnnouncementProject/release related announcements

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions