mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-01-03 13:30:25 +07:00
Annotation system bugs fixed
This commit is contained in:
parent
9e136bad94
commit
c443eee15d
@ -15,10 +15,10 @@ public class Annotations {
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface Remote {
|
||||
/**Whether this method can be invoked on remote clients.*/
|
||||
boolean client() default true;
|
||||
/**Whether this method can be invoked on the remote server.*/
|
||||
boolean server() default false;
|
||||
/**Whether this method can be invoked from remote clients.*/
|
||||
boolean client() default false;
|
||||
/**Whether this method can be invoked from the remote server.*/
|
||||
boolean server() default true;
|
||||
/**Whether a client-specific method is generated that accepts a connecton ID and sends to only one player. Default is false.
|
||||
* Only affects client methods.*/
|
||||
boolean one() default false;
|
||||
|
@ -5,10 +5,10 @@ import io.anuke.annotations.Annotations.WriteClass;
|
||||
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.type.MirroredTypeException;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**This class finds reader and writer methods annotated by the {@link io.anuke.annotations.Annotations.WriteClass}
|
||||
* and {@link io.anuke.annotations.Annotations.ReadClass} annotations.*/
|
||||
@ -26,30 +26,48 @@ public class IOFinder {
|
||||
//look for writers first
|
||||
for(Element writer : writers){
|
||||
WriteClass writean = writer.getAnnotation(WriteClass.class);
|
||||
Class<?> type = writean.value();
|
||||
String typeName = getValue(writean);
|
||||
|
||||
//make sure there's only one read method
|
||||
if(readers.stream().filter(elem -> elem.getAnnotation(ReadClass.class).value() == type).count() > 1){
|
||||
if(readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count() > 1){
|
||||
Utils.messager.printMessage(Kind.ERROR, "Multiple writer methods for type: ", writer);
|
||||
}
|
||||
|
||||
//make sure there's only one write method
|
||||
Stream<? extends Element> stream = readers.stream().filter(elem -> elem.getAnnotation(ReadClass.class).value() == type);
|
||||
if(stream.count() == 0){
|
||||
long count = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count();
|
||||
if(count == 0){
|
||||
Utils.messager.printMessage(Kind.ERROR, "Writer method does not have an accompanying reader: ", writer);
|
||||
}else if(stream.count() > 1){
|
||||
}else if(count > 1){
|
||||
Utils.messager.printMessage(Kind.ERROR, "Writer method has multiple reader for type: ", writer);
|
||||
}
|
||||
|
||||
Element reader = stream.findFirst().get();
|
||||
Element reader = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).findFirst().get();
|
||||
|
||||
//add to result list
|
||||
result.put(type.getName(), new ClassSerializer(Utils.getMethodName(reader), Utils.getMethodName(writer), type.getName()));
|
||||
result.put(typeName, new ClassSerializer(Utils.getMethodName(reader), Utils.getMethodName(writer), typeName));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private String getValue(WriteClass write){
|
||||
try {
|
||||
Class<?> type = write.value();
|
||||
return type.getName();
|
||||
}catch (MirroredTypeException e){
|
||||
return e.getTypeMirror().toString();
|
||||
}
|
||||
}
|
||||
|
||||
private String getValue(ReadClass read){
|
||||
try {
|
||||
Class<?> type = read.value();
|
||||
return type.getName();
|
||||
}catch (MirroredTypeException e){
|
||||
return e.getTypeMirror().toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**Information about read/write methods for a specific class type.*/
|
||||
public static class ClassSerializer{
|
||||
/**Fully qualified method name of the reader.*/
|
||||
|
@ -19,23 +19,11 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
//TODO document
|
||||
//TODO split up into more classes
|
||||
//TODO somehow use annotations to generate serializers for each type?
|
||||
//TODO documentation
|
||||
//TODO custom hash to verify server/client compatibility, just in case!
|
||||
//TODO specify creation class for putting each method
|
||||
//TODO unified Call.functionName() class for more unified usage
|
||||
//TODO error reporting for invalid usage, e.g. method IDs
|
||||
//TODO automatically disable calling on server/client when it's not necessary
|
||||
//TODO autogenerate methods for calling functions for specific clients
|
||||
|
||||
/**The annotation processor for generating remote method call code.*/
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||
@SupportedAnnotationTypes({
|
||||
"io.anuke.annotations.Annotations.RemoteClient",
|
||||
"io.anuke.annotations.Annotations.RemoteServer",
|
||||
"io.anuke.annotations.Annotations.Local",
|
||||
"io.anuke.annotations.Annotations.Unreliable",
|
||||
"io.anuke.annotations.Annotations.In",
|
||||
"io.anuke.annotations.Annotations.Remote",
|
||||
"io.anuke.annotations.Annotations.WriteClass",
|
||||
"io.anuke.annotations.Annotations.ReadClass",
|
||||
})
|
||||
@ -125,10 +113,10 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
||||
RemoteReadGenerator readgen = new RemoteReadGenerator(serializers);
|
||||
RemoteWriteGenerator writegen = new RemoteWriteGenerator(serializers);
|
||||
|
||||
//generate client readers
|
||||
readgen.generateFor(methods.stream().filter(method -> method.client).collect(Collectors.toList()), readClientName, packageName, false);
|
||||
//generate server readers
|
||||
readgen.generateFor(methods.stream().filter(method -> method.server).collect(Collectors.toList()), readServerName, packageName, true);
|
||||
readgen.generateFor(methods.stream().filter(method -> method.client).collect(Collectors.toList()), readServerName, packageName, true);
|
||||
//generate client readers
|
||||
readgen.generateFor(methods.stream().filter(method -> method.server).collect(Collectors.toList()), readClientName, packageName, false);
|
||||
|
||||
//generate the methods to invoke (write)
|
||||
writegen.generateFor(classes, packageName);
|
||||
@ -136,7 +124,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
||||
//create class for storing unique method hash
|
||||
TypeSpec.Builder hashBuilder = TypeSpec.classBuilder("MethodHash").addModifiers(Modifier.PUBLIC);
|
||||
hashBuilder.addField(FieldSpec.builder(int.class, "HASH", Modifier.STATIC, Modifier.PUBLIC, Modifier.FINAL)
|
||||
.initializer("$1L)", Objects.hash(methods)).build());
|
||||
.initializer("$1L", Objects.hash(methods)).build());
|
||||
|
||||
//build and write resulting hash class
|
||||
TypeSpec spec = hashBuilder.build();
|
||||
@ -145,6 +133,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
||||
return true;
|
||||
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ public class RemoteReadGenerator {
|
||||
//end control flow if necessary
|
||||
if(started){
|
||||
readBlock.nextControlFlow("else");
|
||||
readBlock.addStatement("throw new $1N(\"Invalid read method ID: \" + id + \"\")"); //handle invalid method IDs
|
||||
readBlock.addStatement("throw new $1N(\"Invalid read method ID: \" + id + \"\")", RuntimeException.class.getName()); //handle invalid method IDs
|
||||
readBlock.endControlFlow();
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ public class RemoteWriteGenerator {
|
||||
|
||||
//write the 'send even to one player' variant, which is only applicable on the server
|
||||
if(methodEntry.server && methodEntry.oneVariant){
|
||||
writeMethodVariant(classBuilder, methodEntry, true);
|
||||
writeMethodVariant(classBuilder, methodEntry, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +52,7 @@ public class RemoteWriteGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
/**Creates a specific variant for a method entry.*/
|
||||
private void writeMethodVariant(TypeSpec.Builder classBuilder, MethodEntry methodEntry, boolean toAll){
|
||||
ExecutableElement elem = methodEntry.element;
|
||||
|
||||
@ -134,7 +135,7 @@ public class RemoteWriteGenerator {
|
||||
}
|
||||
|
||||
//add statement for writing it
|
||||
method.addStatement(ser.writeMethod + "(buffer, " + varName +")");
|
||||
method.addStatement(ser.writeMethod + "(TEMP_BUFFER, " + varName +")");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,7 @@ public class NetClient extends Module {
|
||||
|
||||
Net.handleClient(InvokePacket.class, packet -> {
|
||||
//TODO invoke it
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.utils.IntMap;
|
||||
import com.badlogic.gdx.utils.TimeUtils;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.gen.RemoteReadServer;
|
||||
import io.anuke.mindustry.net.Administration;
|
||||
import io.anuke.mindustry.net.Administration.PlayerInfo;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
@ -49,7 +50,7 @@ public class NetServer extends Module{
|
||||
|
||||
Net.handleServer(InvokePacket.class, (id, packet) -> {
|
||||
//TODO implement
|
||||
//CallServer.readPacket(packet.writeBuffer, packet.type, connections.get(id));
|
||||
RemoteReadServer.readPacket(packet.writeBuffer, packet.type, connections.get(id));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,18 @@
|
||||
package io.anuke.mindustry.net;
|
||||
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
|
||||
public class NetEvents {
|
||||
|
||||
@Remote(unreliable = true, one = true)
|
||||
public static void callClientMethod(int something, Player player, String str, boolean bool){
|
||||
System.out.println("Called " + something + " ? " + bool);
|
||||
}
|
||||
|
||||
@Remote(local = false)
|
||||
public static void someOtherMethod(Tile tile){
|
||||
System.out.println("Called with tile " + tile);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package io.anuke.mindustry.net;
|
||||
import com.badlogic.gdx.utils.TimeUtils;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.gen.RemoteReadClient;
|
||||
import io.anuke.mindustry.net.Packet.ImportantPacket;
|
||||
import io.anuke.mindustry.net.Packet.UnimportantPacket;
|
||||
|
||||
@ -38,6 +39,7 @@ public class Packets {
|
||||
if(Net.client()){
|
||||
//TODO implement
|
||||
//CallClient.readPacket(buffer, type);
|
||||
RemoteReadClient.readPacket(buffer, type);
|
||||
}else{
|
||||
byte[] bytes = new byte[writeLength];
|
||||
buffer.get(bytes);
|
||||
|
Loading…
Reference in New Issue
Block a user