From 55cd0c2baee5f83a6887e33a3aedcf40f66e2e2c Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 8 May 2018 18:39:52 -0400 Subject: [PATCH] Added basic RMI-like system for network evens --- core/src/io/anuke/mindustry/net/Invoke.java | 125 ++++++++++++++++++ .../src/io/anuke/mindustry/net/NetEvents.java | 2 + core/src/io/anuke/mindustry/net/Packets.java | 29 ++++ .../io/anuke/mindustry/net/Registrator.java | 1 + 4 files changed, 157 insertions(+) create mode 100644 core/src/io/anuke/mindustry/net/Invoke.java diff --git a/core/src/io/anuke/mindustry/net/Invoke.java b/core/src/io/anuke/mindustry/net/Invoke.java new file mode 100644 index 0000000000..2a59ec5755 --- /dev/null +++ b/core/src/io/anuke/mindustry/net/Invoke.java @@ -0,0 +1,125 @@ +package io.anuke.mindustry.net; + +import com.badlogic.gdx.utils.ObjectMap; +import com.badlogic.gdx.utils.reflect.ClassReflection; +import com.badlogic.gdx.utils.reflect.Method; +import com.badlogic.gdx.utils.reflect.ReflectionException; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.net.Net.SendMode; +import io.anuke.mindustry.net.Packets.InvokePacket; +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.util.IOUtils; + +import java.nio.ByteBuffer; + +public class Invoke { + private static ObjectMap> methods = new ObjectMap<>(); + private static ObjectMap classes = new ObjectMap<>(); + + public static void on(Class type, String methodName, Object... args){ + try { + Method method = getMethod(type, methodName); + InvokePacket packet = new InvokePacket(); + packet.args = args; + packet.type = type; + packet.method = method; + packet.args = args; + Net.send(packet, SendMode.tcp); + method.invoke(null, args); + }catch (ReflectionException e){ + throw new RuntimeException(e); + } + } + + static void writeObjects(ByteBuffer buffer, Object[] objects){ + for(Object o : objects){ + Class type = o.getClass(); + + if(type == int.class){ + buffer.putInt((Integer)o); + }else if(type == float.class){ + buffer.putFloat((Float)o); + }else if(type == short.class){ + buffer.putShort((Short)o); + }else if(type == boolean.class){ + buffer.put((byte)((Boolean)o ? 1 : 0)); + }else if(type == byte.class){ + buffer.put((Byte)o); + }else if(type == long.class){ + buffer.putLong((Long)o); + }else if(type == short.class){ + buffer.putShort((Short)o); + }else if(type == Tile.class){ + buffer.putInt(((Tile)o).packedPosition()); + }else if(type == String.class){ + IOUtils.writeString(buffer, (String)o); + } + } + } + + static Object[] readObjects(ByteBuffer buffer, Class[] types){ + Object[] result = new Object[types.length]; + for (int i = 0; i < result.length; i++) { + Class type = types[i]; + Object obj = null; + + if(type == int.class){ + obj = buffer.getInt(); + }else if(type == float.class){ + obj = buffer.getFloat(); + }else if(type == short.class){ + obj = buffer.getShort(); + }else if(type == boolean.class){ + obj = buffer.get() == 1; + }else if(type == byte.class){ + obj = buffer.get(); + }else if(type == long.class){ + obj = buffer.getLong(); + }else if(type == short.class){ + obj = buffer.getShort(); + }else if(type == Tile.class){ + obj = Vars.world.tile(buffer.getInt()); + }else if(type == String.class){ + obj = IOUtils.readString(buffer); + } + + if(obj != null){ + result[i] = obj; + }else{ + throw new RuntimeException("Unable to read object of type '" + type + "'!"); + } + } + + return result; + } + + static Class findClass(String name) throws ReflectionException{ + Class cl = classes.get(name); + if(cl == null){ + cl = ClassReflection.forName(name); + classes.put(name, cl); + } + return cl; + } + + static Method getMethod(Class type, String methodname) throws ReflectionException{ + ObjectMap map = methods.get(type); + + if(map == null){ + map = new ObjectMap<>(); + methods.put(type, map); + } + + Method method = map.get(methodname); + + if(method == null){ + method = ClassReflection.getMethod(type, methodname, null); + map.put(methodname, method); + + } + + return method; + + } + +} diff --git a/core/src/io/anuke/mindustry/net/NetEvents.java b/core/src/io/anuke/mindustry/net/NetEvents.java index 7461b37177..36c4d75701 100644 --- a/core/src/io/anuke/mindustry/net/NetEvents.java +++ b/core/src/io/anuke/mindustry/net/NetEvents.java @@ -1,6 +1,8 @@ package io.anuke.mindustry.net; import com.badlogic.gdx.utils.Pools; +import com.badlogic.gdx.utils.reflect.ClassReflection; +import com.badlogic.gdx.utils.reflect.Method; import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.SyncEntity; diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index a0cce621e1..d84d98163d 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -3,7 +3,9 @@ package io.anuke.mindustry.net; import com.badlogic.gdx.utils.Base64Coder; import com.badlogic.gdx.utils.TimeUtils; import com.badlogic.gdx.utils.reflect.ClassReflection; +import com.badlogic.gdx.utils.reflect.Method; import com.badlogic.gdx.utils.reflect.ReflectionException; +import com.sun.tools.internal.ws.wsdl.document.Import; import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.SyncEntity; @@ -31,6 +33,33 @@ public class Packets { public String addressTCP; } + public static class InvokePacket implements Packet{ + public Object[] args; + public Method method; + public Class type; + + @Override + public void read(ByteBuffer buffer) { + IOUtils.writeString(buffer, method.getName()); + IOUtils.writeString(buffer, type.getName()); + Invoke.writeObjects(buffer, args); + } + + @Override + public void write(ByteBuffer buffer) { + String methodname = IOUtils.readString(buffer); + String typename = IOUtils.readString(buffer); + + try { + type = Invoke.findClass(typename); + method = Invoke.getMethod(type, methodname); + args = Invoke.readObjects(buffer, method.getParameterTypes()); + }catch (ReflectionException e){ + throw new RuntimeException(e); + } + } + } + public static class WorldData extends Streamable{ } diff --git a/core/src/io/anuke/mindustry/net/Registrator.java b/core/src/io/anuke/mindustry/net/Registrator.java index a1ec2465e2..36960edd23 100644 --- a/core/src/io/anuke/mindustry/net/Registrator.java +++ b/core/src/io/anuke/mindustry/net/Registrator.java @@ -40,6 +40,7 @@ public class Registrator { PlayerAdminPacket.class, AdministerRequestPacket.class, TracePacket.class, + InvokePacket.class, }; private static ObjectIntMap> ids = new ObjectIntMap<>();