diff --git a/src/main/java/li/cil/oc2/api/API.java b/src/main/java/li/cil/oc2/api/API.java index e0f100ea..ccdc819c 100644 --- a/src/main/java/li/cil/oc2/api/API.java +++ b/src/main/java/li/cil/oc2/api/API.java @@ -1,8 +1,40 @@ package li.cil.oc2.api; +import com.google.gson.GsonBuilder; +import li.cil.oc2.api.device.DeviceMethod; +import li.cil.oc2.api.device.object.Callback; +import li.cil.oc2.api.imc.DeviceMethodParameterTypeAdapter; + +import java.lang.reflect.Type; + public final class API { public static final String MOD_ID = "oc2"; + /** + * IMC message for registering a {@link li.cil.oc2.api.device.provider.DeviceProvider}. + *
+ * Example: + *
+ * InterModComms.sendTo(API.MOD_ID, API.IMC_ADD_DEVICE_PROVIDER, () -> new DeviceProvider() { ... });
+ *
+ */
+ public static final String IMC_ADD_DEVICE_PROVIDER = "addDeviceProvider";
+
+ /**
+ * IMC message for registering Gson type adapters for method parameter serialization and
+ * deserialization.
+ * + * Must be called with a supplier that provides an instance of {@link DeviceMethodParameterTypeAdapter}. + *
+ * It can be necessary to register additional serializers when implementing {@link DeviceMethod}s + * that use custom parameter types. + * + * @see GsonBuilder#registerTypeAdapter(Type, Object) + * @see DeviceMethod + * @see Callback + */ + public static final String IMC_ADD_DEVICE_METHOD_PARAMETER_TYPE_ADAPTER = "addDeviceMethodParameterTypeAdapter"; + private API() { } } diff --git a/src/main/java/li/cil/oc2/api/device/DeviceMethod.java b/src/main/java/li/cil/oc2/api/device/DeviceMethod.java index d662b50e..3396b947 100644 --- a/src/main/java/li/cil/oc2/api/device/DeviceMethod.java +++ b/src/main/java/li/cil/oc2/api/device/DeviceMethod.java @@ -11,6 +11,10 @@ import java.util.Optional; *
* The easiest and hence recommended way of implementing this interface is to use * the {@link ObjectDevice} class. + *
+ * Method parameters are serialized and deserialized using Gson. When using custom + * parameter types it may be necessary to register a custom type adapter for them + * via {@link li.cil.oc2.api.API#IMC_ADD_DEVICE_METHOD_PARAMETER_TYPE_ADAPTER}. * * @see ObjectDevice */ diff --git a/src/main/java/li/cil/oc2/api/device/object/Callback.java b/src/main/java/li/cil/oc2/api/device/object/Callback.java index bd879006..b5a17ad4 100644 --- a/src/main/java/li/cil/oc2/api/device/object/Callback.java +++ b/src/main/java/li/cil/oc2/api/device/object/Callback.java @@ -13,6 +13,10 @@ import java.lang.annotation.Target; *
* Intended to be used in classes instances of which are used in combination with * {@link ObjectDevice} and subclasses of {@link ObjectDevice}. + *
+ * Method parameters are serialized and deserialized using Gson. When using custom
+ * parameter types it may be necessary to register a custom type adapter for them
+ * via {@link li.cil.oc2.api.API#IMC_ADD_DEVICE_METHOD_PARAMETER_TYPE_ADAPTER}.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
diff --git a/src/main/java/li/cil/oc2/api/imc/DeviceMethodParameterTypeAdapter.java b/src/main/java/li/cil/oc2/api/imc/DeviceMethodParameterTypeAdapter.java
new file mode 100644
index 00000000..d4f98c47
--- /dev/null
+++ b/src/main/java/li/cil/oc2/api/imc/DeviceMethodParameterTypeAdapter.java
@@ -0,0 +1,11 @@
+package li.cil.oc2.api.imc;
+
+public final class DeviceMethodParameterTypeAdapter {
+ public final Class> type;
+ public final Object typeAdapter;
+
+ public DeviceMethodParameterTypeAdapter(final Class> type, final Object typeAdapter) {
+ this.type = type;
+ this.typeAdapter = typeAdapter;
+ }
+}
diff --git a/src/main/java/li/cil/oc2/common/CommonSetup.java b/src/main/java/li/cil/oc2/common/CommonSetup.java
index 29ae9bb3..57ee8076 100644
--- a/src/main/java/li/cil/oc2/common/CommonSetup.java
+++ b/src/main/java/li/cil/oc2/common/CommonSetup.java
@@ -4,19 +4,26 @@ import li.cil.oc2.common.capabilities.DeviceBusElementCapability;
import li.cil.oc2.common.network.Network;
import li.cil.oc2.common.vm.Allocator;
import li.cil.oc2.serialization.BlobStorage;
+import li.cil.oc2.serialization.serializers.ItemStackJsonSerializer;
+import net.minecraft.item.ItemStack;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppedEvent;
+import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
public final class CommonSetup {
public static void run(final FMLCommonSetupEvent event) {
DeviceBusElementCapability.register();
-
+ Providers.initialize();
Network.setup();
+ FMLJavaModLoadingContext.get().getModEventBus().addListener(IMC::handleIMCMessages);
MinecraftForge.EVENT_BUS.addListener(CommonSetup::handleServerAboutToStart);
MinecraftForge.EVENT_BUS.addListener(CommonSetup::handleServerStoppedEvent);
+ ServerScheduler.register();
+
+ addBuiltinDeviceMethodParameterTypeAdapters();
}
public static void handleServerAboutToStart(final FMLServerAboutToStartEvent event) {
@@ -27,4 +34,8 @@ public final class CommonSetup {
BlobStorage.synchronize();
Allocator.resetAndCheckLeaks();
}
+
+ private static void addBuiltinDeviceMethodParameterTypeAdapters() {
+ DeviceMethodParameterTypeAdapters.addTypeAdapter(ItemStack.class, new ItemStackJsonSerializer());
+ }
}
diff --git a/src/main/java/li/cil/oc2/common/IMC.java b/src/main/java/li/cil/oc2/common/IMC.java
new file mode 100644
index 00000000..b91a6f90
--- /dev/null
+++ b/src/main/java/li/cil/oc2/common/IMC.java
@@ -0,0 +1,65 @@
+package li.cil.oc2.common;
+
+import li.cil.oc2.api.API;
+import li.cil.oc2.api.device.provider.DeviceProvider;
+import li.cil.oc2.api.imc.DeviceMethodParameterTypeAdapter;
+import li.cil.oc2.common.device.DeviceMethodParameterTypeAdapters;
+import li.cil.oc2.common.device.Providers;
+import net.minecraft.util.Util;
+import net.minecraftforge.fml.InterModComms;
+import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.HashMap;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+public final class IMC {
+ private static final Logger LOGGER = LogManager.getLogger();
+
+ private static final HashMap