hammy275 / immersive-mc

A Minecraft mod to make Minecraft more immersive!
GNU Lesser General Public License v3.0
61 stars 7 forks source link

API #273

Closed hammy275 closed 1 month ago

hammy275 commented 1 year ago

With #272 , we'll have a really good base to build an API off of for code-driven immersives.

Note that ImmersiveMC will not be switching to semver if I implement this. Instead, I'll make breaking changes between major Minecraft versions if needed, and leave it be otherwise.

Main reason to make an API here is for easier support to add compatibility with other mods.

All immersives that aren't JSON-driven after #272 should use the API to make sure it's good to go.

hammy275 commented 1 year ago

With how the JSON is planned to be built, the API may end up simply being the JSON format

hammy275 commented 1 year ago

The API should actually come BEFORE #272 , especially considering some immersives won't be implementable in JSON.

hammy275 commented 4 months ago

With the work done during the 1.5.0 dev-cycle, I think it only makes sense at this point to target this for 1.5.0.

hammy275 commented 3 months ago

API Planning

This comment will effectively serve as a "document" describing the plans of the API. It will be edited as plans change and evolve. It's written relatively formally, mainly to serve as a guide to myself as I implement the API in-code.

Issues/Ideas with the Plan as Currently Written

Solved Things not Described In Detail Here

Goals/Scope

Interfaces

The API will be built around a few interfaces, which will be exposed in the package com.hammy275.immersivemc.api. Implementations of these interfaces that needs to be done by ImmersiveMC are an implementation detail, and can change at any time. The "contract" created by these interfaces constitute the API. Interfaces requiring an implementation by ImmersiveMC contain a static instance() method, which retrieves an instance of that interface. These names are not final as-of writing.

As a convenience, interfaces implemented by ImmersiveMC might also provide static functions, which simply run the same functions on the instance of the interface.

Convenience Classes

Although at its core, the API is built on interfaces, some convenience classes will be exposed to make development easier. These will be moved to the api package, and must have the portions that are and aren't covered by the API mentioned in docstrings, with visibility changed to match. For exmaple, fields that aren't covered by the API should be made private, to signify that implementors shouldn't be interacting with them. The following classes will be exposed for convenience:

Registration

Mods should be able to register the client information (ImmersiveMCClientRegistration) and the common information (ImmersiveMCRegistration) in any order (common than client or client than common).

For servers, the moment the common registration happens, we can perform any actions ImmersiveMC needs internally. Client registrations for Immersives done on the server are only required to not crash, and may perform any behaviors otherwise.

For clients, when a client or common registration happens, we check if the other registration has occurred for that Immersive. If so, perform actions internally as needed. If not, these internal actions are performed when the other registration is done. These internal actions will also ensure both a client and common registration occur for any Immersive, such as by adding to a list of ResourceLocations when one registration happens, than removing when the other does. On world join, all Immersives that were partially registered in such a manner are logged to chat, but do not impede game functionality otherwise. This mainly serves to make sure mods are unlikely to release with partially-implemented Immersives in this manner without causing crashes or upsetting gameplay otherwise if this were to happen. An exception to this is client-only Immersives, which will not be checked for in common, and if registered to common, are only required to not crash, like when registering client Immersives on a dedicated server.

Immersives will not be able to be "un-registered", and multiple Immersives cannot share the same ID. Registering an Immersive with the same ID as another Immersive will cause a crash. Furthermore, Immersives cannot be registered while a world is loaded on the server, or when in-game on the client. A crash will occur if this happens. Other than this, Immersives can be registered at anytime.

Despite using the term "registration" throughout this, Immersives will not use a registry. It's overkill for ImmersiveMC, and might cause issues when someone with ImmersiveMC joins a server without it (or vice-versa).

The server and client, when both using ImmersiveMC, must have the same Immersives registered in common. The check for this will be imperfect but simple: whenever an immersive is registered, a variable (call it runningHash for now) will be XOR'd with the ResourceLocation of the Immersive. When joining a server, the runningHash is sent from the server to the client, along with the number of Immersives registered on both sides. If either or both of these values mismatch, the client disconnects due to the mismatch, as there is guaranteed to be one. Otherwise, it's very likely that both sides have the same Immersives, so we allow play to proceed. This is intentionally not enforced for the Immersives registered to the client, as client-only Immersives are supported, and thus, aren't known nor needed to be known to the server.

Backwards Compatibility (and Breaking It) and Versioning

Since ImmersiveMC doesn't use semantic versioning, and there are no plans to switch to it (similarly to Minecraft itself), we need to maintain backwards compatibility as much as possible. In semantic versioning terms, upgrades to the "minor" version and the "patch" version are okay under any circumstances, however "major" version changes should be minimal. Barring exceptional circumstances, they should only take place when at least one of the following happen:

To draw a clear line, backwards compatibility is defined as behavior mentioned in the docstrings for classes and interfaces covered by the API. If something is not documented there, it is not part of the API. For example, if an API method throws an exception, but the docstring does not mention such an exception, the exception being thrown is not part of the API, and may be changed at any time without warning. Such an exception is effectively a bug or some form of undefined behavior.

To prevent confusion between multiple version numbers, and to effectively force myself to keep API compatibility strong, there are no current plans to expose an API version number.

Immersive Priorities

Since I plan to add support for many mods in ImmersiveMC, if another mod dev wants to add support for something in their mod that's already in ImmersiveMC, their implementation should have priority. There won't be a priority system, that would be overkill. Instead, the register methods will check if the namespace of the Immersive's ResourceLocation is ImmersiveMC's mod ID. If so, the implementation is placed at the end of the list of Immersives. Otherwise, it's placed at the beginning.

hammy275 commented 3 months ago

To prevent having to refactor everything before making the API, and having to transition all the Immersives in one go, I'll make an adapter that takes an Immersive implementation, and make it work with the current AbstractImmersive system. This will entail:

  1. Writing the API as planned.
  2. Write an ImmersiveAPIAdapter that extends AbstractImmersive (and an equivalent for the Infos), that takes in an Immersive implementation and exposes it in a way AbstractImmersive understands.
  3. Port all of ImmersiveMC's Immersives to the API.
  4. Remove the adaptors and refactor accordingly.
  5. Settle on the final names and organization of all API classes, interfaces, etc.

During the above process, any gaps in the API will make themselves apparent, and can be filled in.

hammy275 commented 3 months ago

https://github.com/hammy275/immersive-mc/commit/9f35d9c73b6c0f344be3a62f3afaa4fa5a591a38 contains part of step 1 as mentioned above, with the flaws of the API implementation as of this comment. ImmersiveRenderHelpers and below have not been implemented, and static versions of methods implemented by ImmersiveMC have also not been added.

hammy275 commented 1 month ago

Tracking for porting of API to currently supported versions. 1.21 will come with the up-port of 1.20.4 when the rest of beta 2 is done.

hammy275 commented 1 month ago

Accidentally left some commented code in ChestInfo, need to remove that.

hammy275 commented 1 month ago

Finally done!