This fixes several issues I had with consuming multi-loader CC:T in
various upstream mods.
- Include /all/ sources in the Forge/Fabric jar. Before it was just the
common classes, and not the core or API.
- Use some Gradle magic to remove superfluous dependencies from the POM
file. Also make sure Cobalt and Netty are present as dependencies.
- Start using minimize() in our shadow jar config again.
- Add support for Fabric. This is mostly pretty simple, though does
require a lot more mixins than Forge.
Half this diff is due to data generators: we run them separately as
some aspects (recipes mostly) are different between the loaders.
- Add integration with Iris (same as our Oculus support) and REI
(mostly the same as our JEI support).
- Generic peripherals only support inventories (or rather
InventoryStorage) right now. Supporting more of the Fabric storage
API is going to be tricky due to the slotted nature of the API: maybe
something to revisit after Transfer API V3 (V4?, I've lost track).
Note, this does /not/ mean I will be publishing a Fabric version of
CC:T. My plan is to rebase CC:R on top of this, hopefully simplifying
the maintenance work on their end and making the two mods a little more
consistent.
My working tree is a mess, so this is not a good commit. I'm making a
bit of a habit of this.
- Fix UserLevel.OWNER check failing on single player servers.
- Correctly handle the "open folder" fake command.
- Some reshuffling of Forge-specific methods to make Fabric slightly
easier.
This commit got away from me, okay? No, I'm not proud of it either.
- Remove our overrides of handleUpdate tag: we now try to detect
whether we're on the client or server inside BlockEntity.load. Alas,
this is needed for Fabric.
- Remove BlockGeneric/TileGeneric entirely: we've slowly whittled this
down over the years, and nowadays we can get away with putting most
of its functionality into subclasses.
This allows us to do some nice things with overriding HorizontalBlock
(or our new HorizontalContainerBlock class), rather than
reimplementing functionality in each class. Though it would be nice
if Java had some sort of trait system :D:
- Simplify a lot of our container class so it's just defined in terms
of a NonNullList<ItemStack>. This also includes a total rewrite of
the disk drive which I'm not ... thrilled about. It ended up being
easier to copy the code from the mc-next branch :D:.
- Try to test some of the gnarly bits of this. Still a /lot/ more to be
done with testing this.
Closes#658
After several weeks of carefully arranging ribbons, we pull the string
and end up with, ... a bit of a messy bow. There were still some things
I'd missed.
- Split the mod into a common (vanilla-only) project and Forge-specific
project. This gives us room to add Fabric support later on.
- Split the project into main/client source sets. This is not currently
statically checked: we'll do that soon.
- Rename block/item/tile entities to use suffixes rather than prefixes.
- TurtlePlayer now returns a fake player, rather than extending from
Forge's implementation.
- Remove "turtle obeys block protection" config option.
- Put some of the more complex turtle actions behind the
PlatformHelper.
Another ugly commit, not thrilled about it:
- Move all config values to a separate Config class.
- Replace ComputerCraft.log with class-specific loggers.
- Replace ComputerCraft.MOD_ID with ComputerCraftAPI.MOD_ID
It's kinda funny looking at all the pre-CC:T proxy code, how much this
has come full circle. I think this design is nicer than what 1.12 did,
but it's still slighly embarassing.
- Add a new ContainerTransfer class to handle moving items between
containers. This is now used for turtle.drop/turtle.suck as well as
inventory methods.
- Any other usages of IItemHandler (which are mostly on turtle
inventories) now use Container and a couple of helper methods.
- Publish javadoc again: for now this is just the common-api
- Remove all dependencies from the published Forge jar. This is
technically not needed (fg.deobf does this anyway), but seems
sensible.
While this does now involve a little more indirection, by having a
single location for all hooks it's much easier to keep event listeners
consistent between loaders.
The diff is pretty noisy (I've inlined some classes, and ClientRegistry
got a big restructure), but functionality should be the same.
Previously we overrode getCapability on our BlockEntity implementations.
While this is the Proper way to do things, it's obviously impossible to
do in a multi-loader environment.
We now subscribe to the AttachCapabilitiesEvent and add our caps that
way. This does require[^1] some nasty invalidation of caps in a couple
of places, which I'm not wild about.
[^1]: I'm not actually sure it does: we invalidate peripherals and wired
elements when neighbours change, so the explicit invalidation probably
isn't useful.
NetworkMessage follows vanilla's Packet much more closely now: the
handler takes a context argument, which varies between the client and
server.
- The server handler just returns the ServerPlayer who sent the
message.
- The client context provides handleXyz(...) methods for each
clientbound packet. Our packet subclasses call the appropriate
method - the implementation of which contains the actual
implementation.
Doing this allows us to move a whole bunch of client-specific code into
the main client package, dropping several @OnlyIn annotations and
generally reducing the risk of accidentally loading client classes on
the server.
We also abstract out some packet sending and general networking code to
make it easier to use in a multi-loader context.
- Replace our usages of DeferredRegistry with a custom
RegistrationHelper. This effectively behaves the same, just without
any references to Forge code!
- Replace any references to ForgeRegistries with a home-grown
Registries class. This just fetches the underlying registry and
proxies the method calls.
- Change recipe serialisers and loot item conditions to be registered
the same way as other entries.
- Move any Forge specific registration code off to the main
ComputerCraft class.
This adds two new modules: common-api and forge-api, which contain the
common and Forge-specific interfaces for CC's Minecraft-specific API.
We add a new PlatformHelper interface, which abstracts over some of the
loader-specific functionality, such as reading registries[^1] or calling
Forge-specific methods. This interface is then implemented in the main
mod, and loaded via ServiceLoaders.
Some other notes on this:
- We now split shared and client-specific source code into separate
modules. This is to make it harder to reference client code on the
server, thus crashing the game.
Eventually we'll split the main mod up too into separate source sets
- this is, of course, a much bigger problem!
- There's currently some nastiness here due to wanting to preserve
binary compatibility of the API. We'll hopefully be able to remove
this when 1.19.3 releases.
- In order to build a separate Forge-specific API jar, we compile the
common sources twice: once for the common jar and once for the Forge
jar.
Getting this to play nicely with IDEs is a little tricky and so we
provide a cct.inlineProject(...) helper to handle everything.
[^1]: We /can/ do this with vanilla's APIs, but it gives a lot of
deprecation warnings. It just ends up being nicer to abstract over it.
We'll do this everywhere eventually, but much easier to do it
incrementally:
- Use checker framework to default all field/methods/parameters to
@Nonnull.
- Start using ErrorProne[1] and NullAway[2] to check for possible null
pointer issues. I did look into using CheckerFramework, but it's much
stricter (i.e. it's actually Correct). This is technically good, but
is a much steeper migration path, which I'm not sure we're prepared
for yet!
[1]: https://github.com/google/error-prone
[2]: https://github.com/uber/NullAway
It should be possible to consume the ComputerCraft's core (i.e.
non-Minecraft code) in other projects, such as emulators. While this
has been possible for years, it's somewhat tricky from a maintenance
perspective - it's very easy to accidentally add an MC dependency
somewhere!
By publishing a separate "core" jar, we can better distinguish the
boundaries between our Lua runtime and the Minecraft-specific code.
Ideally we could have one core project (rather than separate core and
core-api modules), and publish a separate "api" jar, like we do for the
main mod. However, this isn't really possible to express using Maven
dependencies, and so we must resort to this system.
Of course, this is kinda what the Java module system is meant to solve,
but unfortunately getting that working with Minecraft is infeasible.
- Move core-specific config options to a separate CoreConfig class.
- Use class-specific loggers, instead of a global one.
- Use log markers instead of a logComputerErrors option.
- Switch to a fairly standard code format. This is largely based on
IntelliJ defaults, with some minor tweaks applied via editor config.
Should mean people don't need to import a config!
- Use "var" everywhere instead of explicit types. Type inference is a
joy, and I intend to use it to its fullest.
- Start using switch expressions: we couldn't use them before because
IntelliJ does silly things with our previous brace style, but now we
have the luxury of them!