Added basic RMI-like system for network evens

This commit is contained in:
Anuken
2018-05-08 18:39:52 -04:00
parent 6cc1cecf5a
commit 55cd0c2bae
4 changed files with 157 additions and 0 deletions

View File

@ -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<Class, ObjectMap<String, Method>> methods = new ObjectMap<>();
private static ObjectMap<String, Class> 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<String, Method> 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;
}
}

View File

@ -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;

View File

@ -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{
}

View File

@ -40,6 +40,7 @@ public class Registrator {
PlayerAdminPacket.class,
AdministerRequestPacket.class,
TracePacket.class,
InvokePacket.class,
};
private static ObjectIntMap<Class<?>> ids = new ObjectIntMap<>();