package openmods.network.rpc; import com.google.common.base.Preconditions; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.LoaderState; import java.lang.reflect.Method; import openmods.datastore.DataStoreBuilder; import openmods.network.IdSyncManager; import openmods.utils.io.TypeRW; import org.objectweb.asm.Type; public class RpcSetup { public static final String ID_FIELDS_SEPARATOR = ";"; private int currentMethodId = 0; private int currentWrapperId = 0; private final DataStoreBuilder<String, Integer> methodsStoreBuilder; private final DataStoreBuilder<String, Integer> targetsStoreBuilder; RpcSetup() { this.methodsStoreBuilder = IdSyncManager.INSTANCE.createDataStore("rpc_methods", String.class, Integer.class); this.methodsStoreBuilder.setDefaultKeyReaderWriter(); this.methodsStoreBuilder.setValueReaderWriter(TypeRW.VLI_SERIALIZABLE); this.targetsStoreBuilder = IdSyncManager.INSTANCE.createDataStore("rpc_targets", String.class, Integer.class); this.targetsStoreBuilder.setDefaultKeyReaderWriter(); this.targetsStoreBuilder.setValueReaderWriter(TypeRW.VLI_SERIALIZABLE); } public RpcSetup registerInterface(Class<?> intf) { Preconditions.checkState(Loader.instance().isInState(LoaderState.PREINITIALIZATION), "This method can only be called in pre-initialization state"); Preconditions.checkArgument(intf.isInterface(), "Class %s is not interface", intf); for (Method m : intf.getMethods()) { if (m.isAnnotationPresent(RpcIgnore.class)) continue; Preconditions.checkArgument(m.getReturnType() == void.class, "RPC methods cannot have return type (method = %s)", m); MethodParamsCodec.create(m).validate(); String desc = Type.getMethodDescriptor(m); String entry = m.getDeclaringClass().getName() + ID_FIELDS_SEPARATOR + m.getName() + ID_FIELDS_SEPARATOR + desc; if (!methodsStoreBuilder.isRegistered(entry)) methodsStoreBuilder.addEntry(entry, currentMethodId++); } return this; } public RpcSetup registerTargetWrapper(Class<? extends IRpcTarget> wrapperCls) { Preconditions.checkState(Loader.instance().isInState(LoaderState.PREINITIALIZATION), "This method can only be called in pre-initialization state"); targetsStoreBuilder.addEntry(wrapperCls.getName(), currentWrapperId++); return this; } void finish(MethodIdRegistry methodRegistry, TargetWrapperRegistry wrapperRegistry) { methodsStoreBuilder.addVisitor(methodRegistry); methodsStoreBuilder.register(); targetsStoreBuilder.addVisitor(wrapperRegistry); targetsStoreBuilder.register(); } }