@@ -31,17 +31,27 @@ to the list of type names.
3131### Method Name Collisions
3232
3333All ` RPCDevices ` found for a particular ` BlockEntity ` or ` Item ` will be merged, and present as one singular ` RPCDevice `
34- to the virtual machine. This means that not only type names are merged, but ` RPCMethods ` are merged into a single list
35- as well. The system supports method overloading to some degree. However, RPCs are passed from VM to Java as JSON
36- messages, so some overloads that are clearly different on the Java side may lead to ambiguity .
34+ to the virtual machine. This means that not only type names are merged, but ` RPCMethodGroups ` are merged into a single
35+ list as well. In most cases, it is fine to return each ` RPCMethod ` as its own ` RPCMethodGroup ` . For this reason, the
36+ ` RPCMethod ` interface extends the ` RPCMethodGroup ` interface .
3737
38- > The system still does a best-effort attempt: it will try deserializing parameters for ambiguous overloads one after
38+ The system supports method overloading to some degree. ` RPCMethodGroups ` with matching method name and parameter count
39+ are queried one by one, for a method matching a list of parameters. ` RPCMethods ` provide a default implementation for
40+ this, using the declared parameter types to determine if they match.
41+
42+ However, RPCs are passed from VM to Java as JSON messages, so some overloads, that are clearly different on the Java
43+ side, may lead to ambiguity. Specifically, in cases where one JSON serialization can be deserialized into different
44+ types. Most problematic in this area are ` null ` values, since they match any object type parameter.
45+
46+ > The system does a best-effort attempt: it will try deserializing parameters for ambiguous overloads one after
3947> the other, until deserialization for all parameter types succeeds.
4048
4149To avoid ambiguity, it is recommended to pick clear and unique method names where reasonable. This is particularly true
4250for generic ` RPCDevices ` , e.g. devices providing access to common capabilities, which may be provided by various
4351` BlockEntities ` . An example for this are the built-in devices for the ` IEnergyStorage ` capability.
4452
53+ For more control, ` RPCMethodGroups ` may implement custom override resolution via ` findOverload(RPCInvocation) ` .
54+
4555### Device Lifecycle
4656
4757Where needed, the optional interface methods ` mount() ` , ` unmount() ` and ` suspend() ` may be implemented, to react to
@@ -258,6 +268,7 @@ import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider;
258268import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery ;
259269import li.cil.oc2.api.bus.device.rpc.RPCDevice ;
260270import li.cil.oc2.api.bus.device.rpc.RPCMethod ;
271+ import li.cil.oc2.api.bus.device.rpc.RPCMethodGroup ;
261272import li.cil.oc2.api.bus.device.rpc.RPCParameter ;
262273import li.cil.oc2.api.util.Invalidatable ;
263274import net.minecraft.world.level.block.entity.FurnaceBlockEntity ;
@@ -272,7 +283,7 @@ class ModDevice implements RPCDevice {
272283 }
273284
274285 @Override
275- public List<RPCMethod > getMethods () {
286+ public List<RPCMethodGroup > getMethodGroups () {
276287 return Collections . singletonList(new RPCMethod () {
277288 @Override
278289 public String getName () {
@@ -295,8 +306,8 @@ class ModDevice implements RPCDevice {
295306 }
296307
297308 @Override
298- public Object invoke (Object ... parameters ) throws Throwable {
299- final int arg = ( int ) parameters[ 0 ] ;
309+ public Object invoke (RPCInvocation invocation ) {
310+ int arg = invocation . getParameters() . get( 0 ) . getAsInt() ;
300311 if (arg < 0 ) throw new IllegalArgumentException (" Invalid input value!" );
301312 return Math . sqrt(arg);
302313 }
@@ -326,7 +337,8 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
326337import net.minecraftforge.registries.DeferredRegister ;
327338
328339class Providers {
329- static final DeferredRegister<BlockDeviceProvider > BLOCK_DEVICE_PROVIDERS = DeferredRegister . create(BlockDeviceProvider . class, " my_mod_id" );
340+ static final DeferredRegister<BlockDeviceProvider > BLOCK_DEVICE_PROVIDERS =
341+ DeferredRegister . create(BlockDeviceProvider . class, " my_mod_id" );
330342
331343 // Called from mod initialization, if oc2 is present.
332344 static void initialize () {
0 commit comments