oddlama / vane

Immersive and lore friendly enhancements for vanilla Minecraft
MIT License
263 stars 32 forks source link

Planned refactors and improvements (for discussion) #118

Open oddlama opened 2 years ago

oddlama commented 2 years ago

This is just random list of things that might need attention in the future and ideas that need discussion.

Language system overhauls

Language files currently seem like dead weight. They are not editable by users. To make changes, people need to create their own copy and configure vane to use it.

New approach:

Integrated minimalistic HTTP server to serve resource packs.

Ideally mojang just gives us a packet to send full resource packs to clients. But as this is probably not going to happen, we need a workaround to allow:

I have the (slightly insane) idea to "monkeypatch" minecraft's server code to have the socket function as both a minecraft server and an HTTP server simultaneously on the same port. Might be better suited as a proxy patch or plugin but the resulting user experience would be so easy that it should be illegal.

Merge jar files into one

ryantheleach commented 2 years ago

Sorry I've been a little absent, been distracted (playing) minecraft and chasing performance issues after my server launched.

This is going to be a bit of a rambly update, based on what I had been thinking recently.


Custom Item Musings:

I had toyed around a bit with creating a custom-item api myself, as a toy example of how a custom item API might work that could work cross-plugins, but I hadn't committed it as I hadn't managed to get it to a workable state yet.

You have basically come to the same conclusion that I have, in that a custom-items underlying itemstack is a implementation detail that one day may disappear should Mojang bless us with data driven items.

My abstract API had a way of plugins to register custom item discriminators, that could identify a customItem instance registered using a namespace in a registry backwards from custommodeldata, itemtypes, lore, etc.

I had planned to add a way to update/migrate the items on version change as well, but not yet reached it, in order to propose moving vane items to a PDC tag that registers them to a registry.


Language file inspiration from other plugins I've been playing with:

As for Language Files, I had started updating some old plugins, and wanted to change the way their localization worked after working on vane. Personally I think resource packs are a little overkill (at this point in development) but they will clearly be the solution going forward that vanilla minecraft will promote for custom messaging IMO.

Kyori offer https://github.com/KyoriPowered/moonshine/ which is a library that can inflate a proxy class that implements a messaging service interface. It's overly complicated, and undocumented, as it's been abstracted using generics to the point where it could be used for JSX templates for webservice localizations. But there are several Minecraft plugins which use Adventure (even though it has no direct support for Adventure) that have used it to some effect.

I've been pondering how difficult it would be (and whether there would be any benefit!) to getting vane to use this potentially for localizations. But the current setup of vane seems ill-suited to it, so it boils down to whether you like the current system in use in vane.

Basically, moonshine turns

interface MessagingService {
    @Message("localization.lookup.key.BedIsBlocked")
    public void sendBedIsBlocked(@Reciever Audience player, @Placeholder String why);
}

into a class capable of resolving the key to a message bundle / config / etc (via an interface you implement, no automatic support) resolving any placeholder lookups, and resolving the audiences locale etc, which template to use, intermediate formats.

            messagingService = Moonshine.<IMessagingService, Audience>builder(new TypeToken<IMessagingService>() {
                    })
                    .receiverLocatorResolver(new AudienceResolver(), 0)
                    .sourced(new PluginConfigSource())
                    .rendered(new MessageRenderer())
                    .sent(new MessageSender())
                    .resolvingWithStrategy(new Strategy())
                    .create();

So ReceiverLocator is an interface that accepts the method definition, annotations, etc, and returns the recipient of the message.

sourced takes an interface that resolves an intermediate representation (read, a template string) given a recipient and a message key.

rendered takes an interface responsible for finalizating the message type from the intermediate format, and populating it with substituted placeholders (string template arguments) for a given receiver.

the message sender is responsible for sending the message to a given recipient.

The resolvingWithStrategy is responsible for identifying the placeholders in a given method definition, converting them, looking them up, turning them into components, using their output for further lookups etc.

I had quite a lot of trouble understanding moonshine at first, so was planning on forking it for personal use with different names (but canned that idea after I worked out how it worked, as I could now understand the normal names) You can use this if you find the naming / types more comprehensible to work out how moonshine works: https://github.com/RTLBukkit/hazzard but I won't be publishing it.

I'm yet to work out if this can easily be adapted to work with resource packs, (it should be able to cope with it, just whether it's easy to work with) or if that would even be a goal considering how vane's translation system already works.


Basically TLDR; I think you are on a future proof track using resource packs for localization, but given most plugins don't need or use custom textures, their demand is somewhat lessened, and thus better suited to serverside translations, which moonshine makes easy.


Ponderings on versioning configs & lang files in general

I'd also been on a tangent wondering what the best method of migrating lang files / config files etc is, and been in search of a Java library that's capable of transforming configs based on versioning, or snapshotting them in the build system to easily tell if a setting had been customized from the default.

I'd worked with companies previously that treated configuration changes like database migrations, and in-place upgraded them, based on versioning information stored in meta-data, with a class responsible for porting each change based on version number changes. (forwards only).

However this has been traditionally difficult on yaml files under bukkit, as the comments wern't preserved, and the hierarchical nature of yaml, aliases, multiple documents, makes it fairly difficult to know that editing a yaml file programmatically will even take effect.

For this reason, I've started to shy away from using yaml for localization and configuration, like other plugins use, as it's more easily migrated without those features. However, it does mean that it breaks the 'convention' that minecraft admins are used to.


Research has shown that there doesn't appear to be any nice libraries for this that I can see, so best-case is to publish a default configuration that the user shouldn't edit, that shouldn't be loaded by the application to dissuade the user from editing it.

I'm reluctant to actually use these as a fallback, to prevent the user editing them, unless they were contained inside the jar/resource pack.

So when a new update occurs, the default file would just be in-place replaced, and the users file would have an attempted upgrade, with an automatic backup performed. noting any success or failure.

One thought I had, was loading the server side localizations from the (generated) resource pack server side, instead of from another class / resource, not sure why, just that it would seem a prudent way of minimizing the differences between client side translations and server side ones.

ryantheleach commented 2 years ago

Specifically to inheritance for lang files.

Built-in language files with inheritance

Pros:

Cons:

I think that the current approach of copying reference files is the correct way to go, but they need to be clearly labelled as reference or example files, instead of using in-built to the jar files.

Defaulting in the case of missing nodes is ok, but I think this should cause a warning.

The final questions remaining to me, is

  1. Whether user custom files should be attempted to be migrated automatically at all, or just name them .old.versionxyz and replace them if present with the defaults. (awkward, but it's what discordsrv does)
  2. Whether nodes that get changed/removed should be overwritten or somehow displayed as a conflict inside the lang file, or otherwise reported in the console / a report file made.