Partial 7.0 merge - API preview

This commit is contained in:
Anuken
2021-06-02 11:08:08 -04:00
parent ea75a357ca
commit 28b235ef07
531 changed files with 12356 additions and 6286 deletions
+69 -41
View File
@@ -5,33 +5,62 @@ import arc.func.*;
import arc.net.*;
import arc.struct.*;
import arc.util.*;
import arc.util.pooling.*;
import mindustry.gen.*;
import mindustry.net.Packets.*;
import mindustry.net.Streamable.*;
import net.jpountz.lz4.*;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import static arc.util.Log.*;
import static mindustry.Vars.*;
@SuppressWarnings("unchecked")
public class Net{
private static Seq<Prov<? extends Packet>> packetProvs = new Seq<>();
private static Seq<Class<? extends Packet>> packetClasses = new Seq<>();
private static ObjectIntMap<Class<?>> packetToId = new ObjectIntMap<>();
private boolean server;
private boolean active;
private boolean clientLoaded;
private @Nullable StreamBuilder currentStream;
private final Seq<Object> packetQueue = new Seq<>();
private final Seq<Packet> packetQueue = new Seq<>();
private final ObjectMap<Class<?>, Cons> clientListeners = new ObjectMap<>();
private final ObjectMap<Class<?>, Cons2<NetConnection, Object>> serverListeners = new ObjectMap<>();
private final IntMap<StreamBuilder> streams = new IntMap<>();
private final NetProvider provider;
private final LZ4FastDecompressor decompressor = LZ4Factory.fastestInstance().fastDecompressor();
private final LZ4Compressor compressor = LZ4Factory.fastestInstance().fastCompressor();
static{
registerPacket(StreamBegin::new);
registerPacket(StreamChunk::new);
registerPacket(WorldStream::new);
registerPacket(ConnectPacket::new);
//register generated packet classes
Call.registerPackets();
}
/** Registers a new packet type for serialization. */
public static <T extends Packet> void registerPacket(Prov<T> cons){
packetProvs.add(cons);
var t = cons.get();
packetClasses.add(t.getClass());
packetToId.put(t.getClass(), packetProvs.size - 1);
}
public static byte getPacketId(Packet packet){
int id = packetToId.get(packet.getClass(), -1);
if(id == -1) throw new ArcRuntimeException("Unknown packet type: " + packet.getClass());
return (byte)id;
}
public static <T extends Packet> T newPacket(byte id){
return ((Prov<T>)packetProvs.get(id & 0xff)).get();
}
public Net(NetProvider provider){
this.provider = provider;
@@ -39,9 +68,9 @@ public class Net{
public void handleException(Throwable e){
if(e instanceof ArcNetException){
Core.app.post(() -> showError(new IOException("mismatch")));
Core.app.post(() -> showError(new IOException("mismatch", e)));
}else if(e instanceof ClosedChannelException){
Core.app.post(() -> showError(new IOException("alreadyconnected")));
Core.app.post(() -> showError(new IOException("alreadyconnected", e)));
}else{
Core.app.post(() -> showError(e));
}
@@ -171,14 +200,6 @@ public class Net{
active = false;
}
public byte[] compressSnapshot(byte[] input){
return compressor.compress(input);
}
public byte[] decompressSnapshot(byte[] input, int size){
return decompressor.decompress(input, size);
}
/**
* Starts discovering servers on a different thread.
* Callback is run on the main Arc thread.
@@ -195,21 +216,21 @@ public class Net{
}
/** Send an object to all connected clients, or to the server if this is a client.*/
public void send(Object object, SendMode mode){
public void send(Object object, boolean reliable){
if(server){
for(NetConnection con : provider.getConnections()){
con.send(object, mode);
con.send(object, reliable);
}
}else{
provider.sendClient(object, mode);
provider.sendClient(object, reliable);
}
}
/** Send an object to everyone EXCEPT a certain client. Server-side only.*/
public void sendExcept(NetConnection except, Object object, SendMode mode){
public void sendExcept(NetConnection except, Object object, boolean reliable){
for(NetConnection con : getConnections()){
if(con != except){
con.send(object, mode);
con.send(object, reliable);
}
}
}
@@ -235,7 +256,7 @@ public class Net{
/**
* Call to handle a packet being received for the client.
*/
public void handleClientReceived(Object object){
public void handleClientReceived(Packet object){
if(object instanceof StreamBegin b){
streams.put(b.id, currentStream = new StreamBuilder(b));
@@ -251,33 +272,43 @@ public class Net{
handleClientReceived(builder.build());
currentStream = null;
}
}else if(clientListeners.get(object.getClass()) != null){
}else{
int p = object.getPriority();
if(clientLoaded || ((object instanceof Packet) && ((Packet)object).isImportant())){
if(clientLoaded || p == Packet.priorityHigh){
if(clientListeners.get(object.getClass()) != null){
clientListeners.get(object.getClass()).get(object);
}else{
object.handleClient();
}
Pools.free(object);
}else if(!((object instanceof Packet) && ((Packet)object).isUnimportant())){
}else if(p != Packet.priorityLow){
packetQueue.add(object);
}else{
Pools.free(object);
}
}else{
Log.err("Unhandled packet type: '@'!", object);
}
}
/**
* Call to handle a packet being received for the server.
*/
public void handleServerReceived(NetConnection connection, Object object){
if(serverListeners.get(object.getClass()) != null){
serverListeners.get(object.getClass()).get(connection, object);
Pools.free(object);
}else{
Log.err("Unhandled packet type: '@'!", object.getClass());
public void handleServerReceived(NetConnection connection, Packet object){
try{
//handle object normally
if(serverListeners.get(object.getClass()) != null){
serverListeners.get(object.getClass()).get(connection, object);
}else{
object.handleServer(connection);
}
}catch(ValidateException e){
//ignore invalid actions
debug("Validation failed for '@': @", e.player, e.getMessage());
}catch(RuntimeException e){
//ignore indirect ValidateException-s
if(e.getCause() instanceof ValidateException v){
debug("Validation failed for '@': @", v.player, v.getMessage());
}else{
//rethrow if not ValidateException
throw e;
}
}
}
@@ -315,17 +346,13 @@ public class Net{
active = false;
}
public enum SendMode{
tcp, udp
}
/** Networking implementation. */
public interface NetProvider{
/** Connect to a server. */
void connectClient(String ip, int port, Runnable success) throws IOException;
/** Send an object to the server. */
void sendClient(Object object, SendMode mode);
void sendClient(Object object, boolean reliable);
/** Disconnect from the server. */
void disconnectClient();
@@ -355,4 +382,5 @@ public class Net{
closeServer();
}
}
}