Add programmable readers/writers
josephcsible opened this issue ยท 27 comments
I've been thinking of how to add compat with OpenComputers and similar mods. Here's my proposal:
Reader/writer style approach:
Add a new aspect reader (Programmable Reader)
Add a new aspect writer (Programmable Writer)
These both have a bunch of aspects with super-generic names, like "Aspect 1" or "Blue Aspect". If possible, they'd all be of the Any type; if not, we'd have a few of each type.
We'd have an API that let OpenComputers' Lua code do whatever it wanted with the values of these aspects (getting the values set by the Programmable Writer, and setting the values provided by the Programmable Reader).
Proxy style approach:
Have a block that looks like a proxy, but let OpenComputers' Lua code see what its input is and maybe change its output (or maybe even, instead of making a new block, just let regular proxies be manipulated like this).
Thoughts? Which way should I go?
I like that idea. I'll see where I can get with it. (Can you assign this to me?)
I think a combination of both would be ideal.
I had the following thought for an HTTP interface, but this could be generalized for interfacing with things like OC.
Input Interface
A proxy-like block in which you can define a value type (selector), and bind variables with it. So just like the proxy, except that input is only a value type, not a variable.
External systems, such as OC or an HTTP PUT
call, can then update the value of this proxy.
Output Interface
Another proxy-like block in which you can only insert variable cards. This interface exposes the value contained in this variable to external systems, such as OC or HTTP GET
.
The simplest way to do this is probably to add two simple capabilities that other mods can then use, such as IValueInput
and IValueOutput
. These respectively can have the methods setValue
and getValue
.
As I think about this, I only want an IValueOutput with getValue, not an IValueInput with setValue. I think we should make the writer expose that capability itself, and make the reader use that capability of whatever block it's attached to.
So you mean not creating an Input Interface? And instead attaching an IValueOutput
cap to things like OC blocks?
Not sure if I'm understanding you correctly.
I don't think this will be flexible enough in all cases (thinking of HTTP interfacing which would require a separate block in that case). Furthermore, this would require an reader aspect somewhere.
Your understanding seems to be correct. And wouldn't an HTTP interface need a separate block anyway?
I think an actual Input Interface might make more sense from a players-perspective. I think the concept of actual I/O blocks, instead of one O block and I aspect, is easier to understand.
Furthermore, it's not always possible to attach capabilities to blocks, only if that block has a TE.
A simple case where this would not work for example is when someone would make it so that some (TE-less) button trigger a boolean value change. While this would be possible if that button would be able to interact with the capability of a target.
And wouldn't an HTTP interface need a separate block anyway?
Not necessarily, as I see it, input and output interfaces would be flexible enough to accept I/O from anything.
Hmm, I think you may have sightly misunderstood me actually. There will still be a basically-identical input and output part from the player's perspective. The fact that there's only one Java interface would just be an implementation detail.
Also, with the interface with setValue, I feel like it will be problematic to make sure values always get unset when the setting block goes away.
I still think that would complicate implementation in third-party mods too much. Instead of only having to interact with target capabilities, they'd also have to inject a capability into themself.
And it still wouldn't be possible to handle that button use case.
Why would such a button not just be used with a redstone signal and our redstone reader? I'm envisioning this with the specific intention of working with OpenComputers, RFTools Control, TIS-3D, and other programming mods, not just a catch-all for anything that doesn't have a reader/writer right now.
The button thing was just an example. There are other cases where blocks have no capability, but they could be used to provide some kind of input to the network.
I think RFTools Control is even a perfect example of such a block, AFAIK, they are purely network-based and don't have TEs.
There was some item transfer mod as well that works without TEs, but I can't remember the name.
I'm really having trouble thinking of such a use-case. RFTools Control's blocks have TEs (as does every other programming mod's block that I can think of). For other item transfer mods, wouldn't our inventory readers/writers be the better choice for interaction?
RFTools Control's blocks have TEs
Correction: It was XNet I was thinking about, not RFTools Control.
For other item transfer mods, wouldn't our inventory readers/writers be the better choice for interaction?
Not necessarily, someone could use this item transfer to perform logic. (a certain mod does this, can't remember its name)
XNet's cables aren't tile entities, but its connectors are, and its cables by design don't connect to anything except for themselves and its connectors. Also, is Autoverse the mod you're thinking of?
Also, is Autoverse the mod you're thinking of?
Yes, that's it :-)
In any case, I'm still of the opinion that having to attach a capability to the TE that wants to write a value is not a nice solution in this case. Unless you can convince me with a good reason why this would be beneficial.
My main reason is that it avoids caching problems altogether. It makes the other mods not have to worry about unsetting their values when their blocks power down/get destroyed/fly away/whatever.
I don't see a problem with caching, because the value would be persisted in the input interface.
However, I just thought of an argument in favor of doing it with the capability way as you suggested. That way, the whole lazy evaluation chain of ID remains, and values will only be produced by external mods if they are actually needed.
I'll think about it some more.
Ok, thought about it some more, and I agree that it makes sense to do it the way you suggested.
However, it should be as simple as possible for mods to work with this capability. So I suggest adding helper methods and default capability implementations where needed.
@josephcsible I don't think #359 is easily resolvable in the near future though. Programmable I/O could however already work with single activatable aspects.
But it's your issue, so it's up to you how you want to handle it :-)
I consider #359 a blocker to this, since it seems like a big waste to need a block (or at least a part) for each value you want to export.
New idea: ditch the programmable writer, and make the variable store expose that capability instead, where "index" for it would be the inventory index.
Actually, maybe the variable ID makes more sense than the inventory index. (Or not; everywhere else; variable IDs are just an implementation detail)
Reading a variable by id is also a possibility indeed. It could even be more generic, that any network block can be read, just like the network reader part does currently.
(We could then also add this functionality as an aspect to the network reader)
Implemented in c9b0d13
@josephcsible I am working on the HTTP interface part, so I will be implementing (at least part of) this.
In conclusion, the plan is to create a single IValueInterface
capability.
This will have the hasVariable and getVariable methods.
Reading into the network
An aspect inside the network reader that can read values from the target using the IValueInterface
capability.
Writing from the network
External mod blocks must implement the IValueInterface
capability for exposing values to the network.