mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
Network Improvements
This commit is contained in:
@@ -7,23 +7,20 @@ public class GuiBase {
|
||||
private static boolean propertyConfig = true;
|
||||
private static boolean networkplay = false;
|
||||
private static boolean isAndroidport = false;
|
||||
private static boolean interrupted = false;
|
||||
|
||||
public static IGuiBase getInterface() { return guiInterface; }
|
||||
public static void setInterface(IGuiBase i0) { guiInterface = i0; }
|
||||
|
||||
public static IGuiBase getInterface() {
|
||||
return guiInterface;
|
||||
}
|
||||
public static void setInterface(IGuiBase i0) {
|
||||
guiInterface = i0;
|
||||
}
|
||||
public static void enablePropertyConfig(boolean value) { propertyConfig = value; }
|
||||
public static void setIsAndroid(boolean value) { isAndroidport = value; }
|
||||
public static boolean isAndroid() { return isAndroidport; }
|
||||
public static boolean isNetworkplay() {
|
||||
return networkplay;
|
||||
}
|
||||
public static void setNetworkplay(boolean value) {
|
||||
networkplay = value;
|
||||
}
|
||||
public static boolean hasPropertyConfig() {
|
||||
return propertyConfig;
|
||||
}
|
||||
|
||||
public static boolean isNetworkplay() { return networkplay; }
|
||||
public static void setNetworkplay(boolean value) { networkplay = value; }
|
||||
|
||||
public static boolean hasPropertyConfig() { return propertyConfig; }
|
||||
public static void enablePropertyConfig(boolean value) { propertyConfig = value; }
|
||||
|
||||
public static void setInterrupted(boolean value) { interrupted = value; }
|
||||
public static boolean isInterrupted() { return interrupted; }
|
||||
}
|
||||
|
||||
@@ -17,15 +17,9 @@ public class CObjectInputStream extends ObjectInputStream {
|
||||
this.classResolver = classResolver;
|
||||
}
|
||||
|
||||
protected void readStreamHeader() throws IOException {
|
||||
int version = this.readByte() & 255;
|
||||
if (version != 5) {
|
||||
throw new StreamCorruptedException("Unsupported version: " + version);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
|
||||
int type = this.read();
|
||||
int type = read();
|
||||
if (type < 0) {
|
||||
throw new EOFException();
|
||||
} else {
|
||||
@@ -33,8 +27,8 @@ public class CObjectInputStream extends ObjectInputStream {
|
||||
case 0:
|
||||
return super.readClassDescriptor();
|
||||
case 1:
|
||||
String className = this.readUTF();
|
||||
Class<?> clazz = this.classResolver.resolve(className);
|
||||
String className = readUTF();
|
||||
Class<?> clazz = classResolver.resolve(className);
|
||||
return ObjectStreamClass.lookupAny(clazz);
|
||||
default:
|
||||
throw new StreamCorruptedException("Unexpected class descriptor type: " + type);
|
||||
@@ -42,14 +36,14 @@ public class CObjectInputStream extends ObjectInputStream {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
||||
Class clazz;
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = this.classResolver.resolve(desc.getName());
|
||||
} catch (ClassNotFoundException var4) {
|
||||
clazz = classResolver.resolve(desc.getName());
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
clazz = super.resolveClass(desc);
|
||||
}
|
||||
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,26 +6,16 @@ import java.io.ObjectStreamClass;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class CObjectOutputStream extends ObjectOutputStream {
|
||||
static final int TYPE_FAT_DESCRIPTOR = 0;
|
||||
static final int TYPE_THIN_DESCRIPTOR = 1;
|
||||
|
||||
CObjectOutputStream(OutputStream out) throws IOException {
|
||||
super(out);
|
||||
}
|
||||
|
||||
protected void writeStreamHeader() throws IOException {
|
||||
this.writeByte(5);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException {
|
||||
Class<?> clazz = desc.forClass();
|
||||
if (!clazz.isPrimitive() && !clazz.isArray() && !clazz.isInterface() && desc.getSerialVersionUID() != 0L) {
|
||||
this.write(1);
|
||||
this.writeUTF(desc.getName());
|
||||
} else {
|
||||
this.write(0);
|
||||
super.writeClassDescriptor(desc);
|
||||
}
|
||||
|
||||
//we only pass this and the decoder will lookup in the stream (faster method both mobile and desktop)
|
||||
write(TYPE_THIN_DESCRIPTOR);
|
||||
writeUTF(desc.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||
import io.netty.handler.codec.serialization.ClassResolver;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.StreamCorruptedException;
|
||||
@@ -22,20 +23,21 @@ public class CompatibleObjectDecoder extends LengthFieldBasedFrameDecoder {
|
||||
this.classResolver = classResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
|
||||
ByteBuf frame = (ByteBuf)super.decode(ctx, in);
|
||||
if (frame == null) {
|
||||
return null;
|
||||
} else {
|
||||
ObjectInputStream ois = GuiBase.hasPropertyConfig() ?
|
||||
new ObjectInputStream(new ByteBufInputStream(frame, true)):
|
||||
new CObjectInputStream(new ByteBufInputStream(frame, true),this.classResolver);
|
||||
new ObjectInputStream(new LZ4BlockInputStream(new ByteBufInputStream(frame, true))):
|
||||
new CObjectInputStream(new LZ4BlockInputStream(new ByteBufInputStream(frame, true)),this.classResolver);
|
||||
|
||||
Object var5 = null;
|
||||
try {
|
||||
var5 = ois.readObject();
|
||||
} catch (StreamCorruptedException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println(String.format("Version Mismatch: %s", e.getMessage()));
|
||||
} finally {
|
||||
ois.close();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
@@ -20,7 +21,7 @@ public class CompatibleObjectEncoder extends MessageToByteEncoder<Serializable>
|
||||
|
||||
try {
|
||||
bout.write(LENGTH_PLACEHOLDER);
|
||||
oout = GuiBase.hasPropertyConfig() ? new ObjectOutputStream(bout) : new CObjectOutputStream(bout);
|
||||
oout = GuiBase.hasPropertyConfig() ? new ObjectOutputStream(new LZ4BlockOutputStream(bout)) : new CObjectOutputStream(new LZ4BlockOutputStream(bout));
|
||||
oout.writeObject(msg);
|
||||
oout.flush();
|
||||
} finally {
|
||||
|
||||
@@ -7,4 +7,5 @@ import forge.net.client.FGameClient;
|
||||
public interface IOnlineLobby {
|
||||
ILobbyView setLobby(GameLobby lobby);
|
||||
void setClient(FGameClient client);
|
||||
void closeConn(String msg);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import forge.properties.ForgeConstants;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.interfaces.IGuiGame;
|
||||
import forge.interfaces.ILobbyListener;
|
||||
import forge.interfaces.ILobbyView;
|
||||
@@ -146,8 +145,8 @@ public class NetConnectUtil {
|
||||
}
|
||||
@Override
|
||||
public final void close() {
|
||||
SOptionPane.showMessageDialog("Your connection to the host (" + url + ") was interrupted.", "Error", FSkinProp.ICO_WARNING);
|
||||
onlineLobby.setClient(null);
|
||||
GuiBase.setInterrupted(true);
|
||||
onlineLobby.closeConn("Your connection to the host (" + url + ") was interrupted.");
|
||||
}
|
||||
@Override
|
||||
public ClientGameLobby getLobby() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.net;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import forge.GuiBase;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.deck.CardPool;
|
||||
import forge.game.GameEntityView;
|
||||
@@ -155,28 +156,16 @@ public enum ProtocolMethod {
|
||||
}
|
||||
|
||||
public void checkArgs(final Object[] args) {
|
||||
if(!GuiBase.hasPropertyConfig())
|
||||
return; //if the experimental network option is enabled, then check the args, else let the default decoder handle it
|
||||
|
||||
for (int iArg = 0; iArg < args.length; iArg++) {
|
||||
final Object arg = args[iArg];
|
||||
final Class<?> type = this.args[iArg];
|
||||
if (!ReflectionUtil.isInstance(arg, type)) {
|
||||
//throw new InternalError(String.format("Protocol method %s: illegal argument (%d) of type %s, %s expected", name(), iArg, arg.getClass().getName(), type.getName()));
|
||||
System.err.println(String.format("InternalError: Protocol method %s: illegal argument (%d) of type %s, %s expected (ProtocolMethod.java Line 163)", name(), iArg, arg.getClass().getName(), type.getName()));
|
||||
System.err.println(String.format("InternalError: Protocol method %s: illegal argument (%d) of type %s, %s expected (ProtocolMethod.java)", name(), iArg, arg.getClass().getName(), type.getName()));
|
||||
}
|
||||
//this should be handled via decoder or it will process them twice
|
||||
/*if (arg != null) {
|
||||
// attempt to Serialize each argument, this will throw an exception if it can't.
|
||||
try {
|
||||
byte[] serialized = SerializationUtils.serialize((Serializable) arg);
|
||||
SerializationUtils.deserialize(serialized);
|
||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
||||
// not sure why this one would be thrown, but it is
|
||||
// it also doesn't prevent things from working, so, log for now, pending full network rewrite
|
||||
ex.printStackTrace();
|
||||
} catch(ConcurrentModificationException ex) {
|
||||
// can't seem to avoid this from periodically happening
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +176,7 @@ public enum ProtocolMethod {
|
||||
}
|
||||
if (!ReflectionUtil.isInstance(value, returnType)) {
|
||||
//throw new IllegalStateException(String.format("Protocol method %s: illegal return object type %s returned by client, expected %s", name(), value.getClass().getName(), getReturnType().getName()));
|
||||
System.err.println(String.format("IllegalStateException: Protocol method %s: illegal return object type %s returned by client, expected %s (ProtocolMethod.java Line 190)", name(), value.getClass().getName(), getReturnType().getName()));
|
||||
System.err.println(String.format("IllegalStateException: Protocol method %s: illegal return object type %s returned by client, expected %s (ProtocolMethod.java)", name(), value.getClass().getName(), getReturnType().getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,12 +40,12 @@ public class NetGameController implements IGameController {
|
||||
|
||||
@Override
|
||||
public void selectPlayer(final PlayerView playerView, final ITriggerEvent triggerEvent) {
|
||||
send(ProtocolMethod.selectPlayer, playerView, triggerEvent);
|
||||
send(ProtocolMethod.selectPlayer, playerView, null/*triggerEvent*/); //some platform don't have mousetriggerevent class or it will not allow them to click/tap
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean selectCard(final CardView cardView, final List<CardView> otherCardViewsToSelect, final ITriggerEvent triggerEvent) {
|
||||
send(ProtocolMethod.selectCard, cardView, otherCardViewsToSelect, triggerEvent);
|
||||
send(ProtocolMethod.selectCard, cardView, otherCardViewsToSelect, null/*triggerEvent*/); //some platform don't have mousetriggerevent class or it will not allow them to click/tap
|
||||
// Difference from local games! Always consider a card as successfully selected,
|
||||
// to avoid blocks where server and client wait for each other to respond.
|
||||
// Some cost in functionality but a huge gain in stability & speed.
|
||||
|
||||
@@ -41,7 +41,7 @@ public class NetGuiGame extends AbstractGuiGame {
|
||||
return sender.sendAndWait(method, args);
|
||||
}
|
||||
|
||||
private void updateGameView() {
|
||||
public void updateGameView() {
|
||||
send(ProtocolMethod.setGameView, getGameView());
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ public class NetGuiGame extends AbstractGuiGame {
|
||||
|
||||
@Override
|
||||
public SpellAbilityView getAbilityToPlay(final CardView hostCard, final List<SpellAbilityView> abilities, final ITriggerEvent triggerEvent) {
|
||||
return sendAndWait(ProtocolMethod.getAbilityToPlay, hostCard, abilities, triggerEvent);
|
||||
return sendAndWait(ProtocolMethod.getAbilityToPlay, hostCard, abilities, null/*triggerEvent*/); //someplatform don't have mousetriggerevent class or it will not allow them to click/tap
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user