CC: Tweaked

CC: Tweaked

42M Downloads

Generic peripheral overhaul suggestion

SirEdvin opened this issue · 3 comments

commented

So, this is a slight follow-up to #1093 and #899.

The current generic peripheral holds two major problems for add-on development:

  1. There is no good way to attach inventory or fluid_storage peripherals to peripherals that the add-on built. This leads to issues like this: with the introduction of new functionality, old functionality is lost. There is only one way to solve this: the modder can copy or re-implement all generic peripherals by himself (this is kind of what UPW does), but aside from the fact that CC:T generic peripherals often tested better, understanding the source of the issue with chest peripherals or something else quickly becomes a tricky problem.
  2. inventory generic peripheral, as well as others that attach to Forge/Fabric specific logic, are not extendable. So, there is no way to provide some new cases when StorageWrapper for specific peripheral can be built. This may sound unnecessary because implementation of Fabric/Forge storage logic is often required, but in a lot of cases, such as storage mod integrations or specific use cases built around entities, providing fabric/forge logic for storage just breaks the internal logic of the mod or Minecraft for the player.

To solve this, I can suggest the next plan to solve these two issues:

  1. Introducing an API for "plugins"1 (or whatever name suits better), basically a more extended version of IDynamicPeripheral, that can accept "plugins" and then expose their methods as their own2. This will also help add-on developers build their functionality in a more flexible way if this becomes an official API.
  2. Create multi-loader item/fluid/energy storage interfaces3, which can be implemented anyhow, and "plugins" for inventory, fluid_storage and energy_storage around them. This is probably the weakest point of this plan because CC:T isn't generally built for it.
  3. Introduce APIs for building plugins for any storage that implements interfaces and also to wrap fabric/forge plugin to interfaces. So CC:T will not expose implementation directly, but rather an ability to just get plugins for your storage.
  4. Add the ability to create storage extraction logic when the default is not catching up.

I can try to implement some steps myself, but I would like to discuss the implementation first before starting to write the code.

There is also a possibility for this to be implemented in some kind of official CC:T modding toolkit rather than the CC:T repository, but I am not sure if this idea is bad or good.

Footnotes

  1. I am not sure if the "plugin" term is suitable here, so if anyone has something better, I will rename it.

  2. There is a reference implementation of this in Peripheralium, which I use, but it is not good enough, I suppose.

  3. There is also a reference implementation of this in Peripheralium which I love and hate at the same time, especially the problem with fabric transaction handling.

commented

So ... can I ask for any thoughts about this? :)

commented

Heads up: this is going to be a ramble, and not really address all of these points in any sensible way:

When the generic peripheral system was first implemented, I made a conscious choice to keep the API as small as possible. Plethora's API (and internals!) were incredibly complex, and I wanted to avoid that as much as possible. I'm definitely open to changing/fleshing it out (it really was meant to be the simplest thing, and surprised it's lasted this long), but fear a lot of what you're proposing reaches Plethora-level complexity.

Not 100% related, but it's probably worth mentioning dan200/ComputerCraft#153 and #633 here. They do somewhat influence the current design of generic peripherals, and solving them would probably simplify some things, I've just never been sure about whether they're actually a good idea.

One of the main aims of the generic peripheral system is that it's an inversion of the normal peripheral provider system. Rather than defining a peripheral for a block and providing all the methods for it, you're effectively mixing-in methods onto a specific type1.

This works pretty well when you stay in generic-peripheral land, as it allows multiple mods to inject methods onto the same block2. However, if a mod wants/needs a dedicated IPeripheral it does all fall apart.

I find it really hard to know what to do with this issue, because there's two types of problem here, and I'm not sure how to disentangle them:

  • Issues encountered due to the fact that Peripheralium reinvents the generic peripheral system: For instance, the create tanks integration, is a perfect example of what GenericPeripheral was designed for!
  • Issues with the generic peripheral system that required Peripheralium reinventing it.

I do think it'd be interesting (though a lot of work, and I know you're busy working on other things!) to see what could be ported over to use GenericPeripheral, and where you start hitting issues. I suspect #839 and #899 are the main problems, but don't know for sure.

Footnotes

  1. Fun facts, this system actually works anywhere - it's possible to use a GenericSource to add methods to any peripheral or Lua object.

  2. Though the lack of priorities is a pain. Again, closely related to the multi-peripheral issue.

commented

There have been some changes to generic methods in the last few months, and would be interesting to see if this helps in any way:

  • Support for custom "lookup" functions (0ff58cd), rather than hard coding our list of ItemStorage. This isn't part of the public API (at least yet), but I don't think that matters for you :p.

  • Support for instance methods (fe826f5, 84a799d). Relatively minor, but should make at least make it easier to write generic methods in Kotlin.