initial commit
This commit is contained in:
parent
3c9ee26b06
commit
22186c33b9
1458 changed files with 282792 additions and 0 deletions
9
java/src/game/network/IThreadListener.java
Executable file
9
java/src/game/network/IThreadListener.java
Executable file
|
@ -0,0 +1,9 @@
|
|||
package game.network;
|
||||
|
||||
import game.future.ListenableFuture;
|
||||
|
||||
public interface IThreadListener
|
||||
{
|
||||
ListenableFuture<Object> schedule(Runnable run);
|
||||
boolean isMainThread();
|
||||
}
|
20
java/src/game/network/LazyLoadBase.java
Executable file
20
java/src/game/network/LazyLoadBase.java
Executable file
|
@ -0,0 +1,20 @@
|
|||
package game.network;
|
||||
|
||||
public abstract class LazyLoadBase<T>
|
||||
{
|
||||
private T value;
|
||||
private boolean isLoaded = false;
|
||||
|
||||
public T getValue()
|
||||
{
|
||||
if (!this.isLoaded)
|
||||
{
|
||||
this.isLoaded = true;
|
||||
this.value = this.load();
|
||||
}
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
protected abstract T load();
|
||||
}
|
484
java/src/game/network/NetConnection.java
Executable file
484
java/src/game/network/NetConnection.java
Executable file
|
@ -0,0 +1,484 @@
|
|||
package game.network;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import game.Log;
|
||||
import game.future.ThreadFactoryBuilder;
|
||||
import game.net.bootstrap.Bootstrap;
|
||||
import game.net.channel.Channel;
|
||||
import game.net.channel.ChannelException;
|
||||
import game.net.channel.ChannelFuture;
|
||||
import game.net.channel.ChannelFutureListener;
|
||||
import game.net.channel.ChannelHandler;
|
||||
import game.net.channel.ChannelHandlerContext;
|
||||
import game.net.channel.ChannelInitializer;
|
||||
import game.net.channel.ChannelOption;
|
||||
import game.net.channel.EventLoopGroup;
|
||||
import game.net.channel.SimpleChannelInboundHandler;
|
||||
import game.net.channel.local.LocalChannel;
|
||||
import game.net.channel.local.LocalEventLoopGroup;
|
||||
import game.net.channel.local.LocalServerChannel;
|
||||
import game.net.channel.nio.NioEventLoopGroup;
|
||||
import game.net.channel.socket.SocketChannel;
|
||||
import game.net.channel.socket.nio.NioSocketChannel;
|
||||
import game.net.handler.timeout.ReadTimeoutHandler;
|
||||
import game.net.handler.timeout.TimeoutException;
|
||||
import game.net.util.AttributeKey;
|
||||
import game.net.util.concurrent.Future;
|
||||
import game.net.util.concurrent.GenericFutureListener;
|
||||
import game.network.NetHandler.ThreadQuickExitException;
|
||||
|
||||
public class NetConnection extends SimpleChannelInboundHandler<Packet>
|
||||
{
|
||||
private static final Pattern IP_REPLACER = Pattern.compile("([0-9]*)\\.([0-9]*)\\.[0-9]*\\.[0-9]*");
|
||||
public static final AttributeKey<PacketRegistry> ATTR_STATE = AttributeKey.<PacketRegistry>valueOf("protocol");
|
||||
public static final LazyLoadBase<NioEventLoopGroup> CLIENT_NIO_EVENTLOOP = new LazyLoadBase<NioEventLoopGroup>()
|
||||
{
|
||||
protected NioEventLoopGroup load()
|
||||
{
|
||||
return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).build());
|
||||
}
|
||||
};
|
||||
// public static final LazyLoadBase<EpollEventLoopGroup> CLIENT_EPOLL_EVENTLOOP = new LazyLoadBase<EpollEventLoopGroup>()
|
||||
// {
|
||||
// protected EpollEventLoopGroup load()
|
||||
// {
|
||||
// return new EpollEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Epoll Client IO #%d").setDaemon(true).build());
|
||||
// }
|
||||
// };
|
||||
public static final LazyLoadBase<LocalEventLoopGroup> CLIENT_LOCAL_EVENTLOOP = new LazyLoadBase<LocalEventLoopGroup>()
|
||||
{
|
||||
protected LocalEventLoopGroup load()
|
||||
{
|
||||
return new LocalEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).build());
|
||||
}
|
||||
};
|
||||
// private final PacketDirection direction;
|
||||
private final Queue<NetConnection.InboundHandlerTuplePacketListener> outboundPacketsQueue = new ConcurrentLinkedQueue<InboundHandlerTuplePacketListener>();
|
||||
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
|
||||
|
||||
private Channel channel;
|
||||
private SocketAddress socketAddress;
|
||||
private NetHandler packetListener;
|
||||
private String terminationReason;
|
||||
private boolean disconnected;
|
||||
private boolean local;
|
||||
|
||||
// public NetConnection(PacketDirection packetDirection)
|
||||
// {
|
||||
// this.direction = packetDirection;
|
||||
// }
|
||||
|
||||
public void channelActive(ChannelHandlerContext p_channelActive_1_) throws Exception
|
||||
{
|
||||
super.channelActive(p_channelActive_1_);
|
||||
this.channel = p_channelActive_1_.channel();
|
||||
this.local = this.channel instanceof LocalChannel || this.channel instanceof LocalServerChannel;
|
||||
this.socketAddress = this.channel.remoteAddress();
|
||||
|
||||
try
|
||||
{
|
||||
this.setConnectionState(PacketRegistry.HANDSHAKE);
|
||||
}
|
||||
catch (Throwable throwable)
|
||||
{
|
||||
Log.JNI.error(throwable, "Fehler beim Aufbauen der Verbindung für Handshake");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new connection state and registers which packets this channel may send and receive
|
||||
*/
|
||||
public void setConnectionState(PacketRegistry newState)
|
||||
{
|
||||
this.channel.attr(ATTR_STATE).set(newState);
|
||||
this.channel.config().setAutoRead(true);
|
||||
// Log.debug("Automatisches Lesen eingeschaltet");
|
||||
}
|
||||
|
||||
public void channelInactive(ChannelHandlerContext p_channelInactive_1_) throws Exception
|
||||
{
|
||||
this.closeChannel("Ende der Datenübertragung");
|
||||
}
|
||||
|
||||
public void exceptionCaught(ChannelHandlerContext p_exceptionCaught_1_, Throwable p_exceptionCaught_2_) throws Exception
|
||||
{
|
||||
String comp;
|
||||
|
||||
if (p_exceptionCaught_2_ instanceof TimeoutException)
|
||||
{
|
||||
comp = "Zeitüberschreitung";
|
||||
}
|
||||
else
|
||||
{
|
||||
comp = "Interner Fehler: " + p_exceptionCaught_2_;
|
||||
}
|
||||
|
||||
this.closeChannel(comp);
|
||||
}
|
||||
|
||||
protected void channelRead0(ChannelHandlerContext p_channelRead0_1_, Packet p_channelRead0_2_) throws Exception
|
||||
{
|
||||
if (this.channel.isOpen())
|
||||
{
|
||||
try
|
||||
{
|
||||
p_channelRead0_2_.processPacket(this.packetListener);
|
||||
}
|
||||
catch (ThreadQuickExitException e)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the NetHandler for this NetworkManager, no checks are made if this handler is suitable for the particular
|
||||
* connection state (protocol)
|
||||
*/
|
||||
public void setNetHandler(NetHandler handler)
|
||||
{
|
||||
if (handler == null) {
|
||||
throw new NullPointerException("Handler ist Null");
|
||||
}
|
||||
// Log.debug("Setze Handler von " + this + " auf " + handler);
|
||||
this.packetListener = handler;
|
||||
}
|
||||
|
||||
public void sendPacket(Packet packetIn)
|
||||
{
|
||||
if (this.isChannelOpen())
|
||||
{
|
||||
this.flushOutboundQueue();
|
||||
this.dispatchPacket(packetIn, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.readWriteLock.writeLock().lock();
|
||||
|
||||
try
|
||||
{
|
||||
this.outboundPacketsQueue.add(new NetConnection.InboundHandlerTuplePacketListener(packetIn, null));
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.readWriteLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendPacket(Packet packetIn, GenericFutureListener <? extends Future <? super Void >> listener)
|
||||
{
|
||||
if (this.isChannelOpen())
|
||||
{
|
||||
this.flushOutboundQueue();
|
||||
this.dispatchPacket(packetIn, new GenericFutureListener[] {listener});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.readWriteLock.writeLock().lock();
|
||||
|
||||
try
|
||||
{
|
||||
this.outboundPacketsQueue.add(new NetConnection.InboundHandlerTuplePacketListener(packetIn, listener));
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.readWriteLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will commit the packet to the channel. If the current thread 'owns' the channel it will write and flush the
|
||||
* packet, otherwise it will add a task for the channel eventloop thread to do that.
|
||||
*/
|
||||
private void dispatchPacket(final Packet inPacket, final GenericFutureListener <? extends Future <? super Void >> [] futureListeners)
|
||||
{
|
||||
final PacketRegistry enumconnectionstate = PacketRegistry.getType(inPacket);
|
||||
final PacketRegistry enumconnectionstate1 = (PacketRegistry)this.channel.attr(ATTR_STATE).get();
|
||||
|
||||
if (enumconnectionstate1 != enumconnectionstate)
|
||||
{
|
||||
// Log.debug("Automatisches Lesen ausgeschaltet");
|
||||
this.channel.config().setAutoRead(false);
|
||||
}
|
||||
|
||||
if (this.channel.eventLoop().inEventLoop())
|
||||
{
|
||||
if (enumconnectionstate != enumconnectionstate1)
|
||||
{
|
||||
this.setConnectionState(enumconnectionstate);
|
||||
}
|
||||
|
||||
ChannelFuture channelfuture = this.channel.writeAndFlush(inPacket);
|
||||
|
||||
if (futureListeners != null)
|
||||
{
|
||||
channelfuture.addListeners(futureListeners);
|
||||
}
|
||||
|
||||
channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.channel.eventLoop().execute(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
if (enumconnectionstate != enumconnectionstate1)
|
||||
{
|
||||
NetConnection.this.setConnectionState(enumconnectionstate);
|
||||
}
|
||||
|
||||
ChannelFuture channelfuture1 = NetConnection.this.channel.writeAndFlush(inPacket);
|
||||
|
||||
if (futureListeners != null)
|
||||
{
|
||||
channelfuture1.addListeners(futureListeners);
|
||||
}
|
||||
|
||||
channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will iterate through the outboundPacketQueue and dispatch all Packets
|
||||
*/
|
||||
private void flushOutboundQueue()
|
||||
{
|
||||
if (this.channel != null && this.channel.isOpen())
|
||||
{
|
||||
this.readWriteLock.readLock().lock();
|
||||
|
||||
try
|
||||
{
|
||||
while (!this.outboundPacketsQueue.isEmpty())
|
||||
{
|
||||
NetConnection.InboundHandlerTuplePacketListener networkmanager$inboundhandlertuplepacketlistener = (NetConnection.InboundHandlerTuplePacketListener)this.outboundPacketsQueue.poll();
|
||||
if(networkmanager$inboundhandlertuplepacketlistener != null) { // NPE Fix
|
||||
this.dispatchPacket(networkmanager$inboundhandlertuplepacketlistener.packet, networkmanager$inboundhandlertuplepacketlistener.futureListeners);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.readWriteLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks timeouts and processes all packets received
|
||||
*/
|
||||
public void processReceivedPackets()
|
||||
{
|
||||
this.flushOutboundQueue();
|
||||
this.packetListener.update();
|
||||
// if (this.packetListener instanceof ITickable)
|
||||
// {
|
||||
// ((ITickable)this.packetListener).update();
|
||||
// }
|
||||
this.channel.flush();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Returns the socket address of the remote side. Server-only.
|
||||
// */
|
||||
// public SocketAddress getRemoteAddress()
|
||||
// {
|
||||
// return this.socketAddress;
|
||||
// }
|
||||
|
||||
public String getCutAddress() {
|
||||
return this.socketAddress == null ? "?.?.*.*" : IP_REPLACER.matcher(this.socketAddress.toString()).replaceAll("$1.$2.*.*");
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the channel, the parameter can be used for an exit message (not certain how it gets sent)
|
||||
*/
|
||||
public void closeChannel(String message)
|
||||
{
|
||||
if (this.channel.isOpen())
|
||||
{
|
||||
this.channel.close().awaitUninterruptibly();
|
||||
this.terminationReason = message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this NetworkManager uses a memory connection (single player game). False may imply both an active TCP
|
||||
* connection or simply no active connection at all
|
||||
*/
|
||||
public boolean isLocalChannel()
|
||||
{
|
||||
return this.local;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new NetworkManager from the server host and connect it to the server
|
||||
*
|
||||
* @param address The address of the server
|
||||
* @param serverPort The server port
|
||||
*/
|
||||
public static NetConnection createNetworkManagerAndConnect(InetAddress address, int serverPort)
|
||||
{
|
||||
final NetConnection networkmanager = new NetConnection();
|
||||
Class <? extends SocketChannel > oclass;
|
||||
LazyLoadBase <? extends EventLoopGroup > lazyloadbase;
|
||||
|
||||
// if (Epoll.isAvailable())
|
||||
// {
|
||||
// oclass = EpollSocketChannel.class;
|
||||
// lazyloadbase = CLIENT_EPOLL_EVENTLOOP;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
oclass = NioSocketChannel.class;
|
||||
lazyloadbase = CLIENT_NIO_EVENTLOOP;
|
||||
// }
|
||||
|
||||
((Bootstrap)((Bootstrap)((Bootstrap)(new Bootstrap()).group((EventLoopGroup)lazyloadbase.getValue())).handler(new ChannelInitializer<Channel>()
|
||||
{
|
||||
protected void initChannel(Channel p_initChannel_1_) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
p_initChannel_1_.config().setOption(ChannelOption.TCP_NODELAY, Boolean.valueOf(true));
|
||||
}
|
||||
catch (ChannelException var3)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
p_initChannel_1_.pipeline().addLast((String)"timeout", (ChannelHandler)(new ReadTimeoutHandler(30))).addLast((String)"splitter", (ChannelHandler)(new PacketSplitter())).addLast((String)"decoder", (ChannelHandler)(new PacketDecoder(false))).addLast((String)"prepender", (ChannelHandler)(new PacketPrepender())).addLast((String)"encoder", (ChannelHandler)(new PacketEncoder(true))).addLast((String)"packet_handler", (ChannelHandler)networkmanager);
|
||||
}
|
||||
})).channel(oclass)).connect(address, serverPort).syncUninterruptibly();
|
||||
return networkmanager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a clientside NetworkManager: establishes a connection to the socket supplied and configures the channel
|
||||
* pipeline. Returns the newly created instance.
|
||||
*/
|
||||
public static NetConnection provideLocalClient(SocketAddress address)
|
||||
{
|
||||
final NetConnection networkmanager = new NetConnection();
|
||||
((Bootstrap)((Bootstrap)((Bootstrap)(new Bootstrap()).group((EventLoopGroup)CLIENT_LOCAL_EVENTLOOP.getValue())).handler(new ChannelInitializer<Channel>()
|
||||
{
|
||||
protected void initChannel(Channel p_initChannel_1_) throws Exception
|
||||
{
|
||||
p_initChannel_1_.pipeline().addLast((String)"packet_handler", (ChannelHandler)networkmanager);
|
||||
}
|
||||
})).channel(LocalChannel.class)).connect(address).syncUninterruptibly();
|
||||
return networkmanager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this NetworkManager has an active channel, false otherwise
|
||||
*/
|
||||
public boolean isChannelOpen()
|
||||
{
|
||||
return this.channel != null && this.channel.isOpen();
|
||||
}
|
||||
|
||||
public boolean hasNoChannel()
|
||||
{
|
||||
return this.channel == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current handler for processing packets
|
||||
*/
|
||||
public NetHandler getNetHandler()
|
||||
{
|
||||
return this.packetListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the channel to manual reading modus
|
||||
*/
|
||||
public void disableAutoRead()
|
||||
{
|
||||
this.channel.config().setAutoRead(false);
|
||||
}
|
||||
|
||||
public void setCompressionTreshold(int treshold)
|
||||
{
|
||||
if (treshold >= 0)
|
||||
{
|
||||
if (this.channel.pipeline().get("decompress") instanceof NettyCompressionDecoder)
|
||||
{
|
||||
((NettyCompressionDecoder)this.channel.pipeline().get("decompress")).setCompressionTreshold(treshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.channel.pipeline().addBefore("decoder", "decompress", new NettyCompressionDecoder(treshold));
|
||||
}
|
||||
|
||||
if (this.channel.pipeline().get("compress") instanceof NettyCompressionEncoder)
|
||||
{
|
||||
((NettyCompressionEncoder)this.channel.pipeline().get("compress")).setCompressionTreshold(treshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.channel.pipeline().addBefore("encoder", "compress", new NettyCompressionEncoder(treshold));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.channel.pipeline().get("decompress") instanceof NettyCompressionDecoder)
|
||||
{
|
||||
this.channel.pipeline().remove("decompress");
|
||||
}
|
||||
|
||||
if (this.channel.pipeline().get("compress") instanceof NettyCompressionEncoder)
|
||||
{
|
||||
this.channel.pipeline().remove("compress");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void checkDisconnected()
|
||||
{
|
||||
if (this.channel != null && !this.channel.isOpen())
|
||||
{
|
||||
if (!this.disconnected)
|
||||
{
|
||||
this.disconnected = true;
|
||||
|
||||
if (this.terminationReason != null)
|
||||
{
|
||||
this.getNetHandler().onDisconnect(this.terminationReason);
|
||||
}
|
||||
else if (this.getNetHandler() != null)
|
||||
{
|
||||
this.getNetHandler().onDisconnect("Verbindung getrennt");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.JNI.warn("handleDisconnection() zweifach aufgerufen");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class InboundHandlerTuplePacketListener
|
||||
{
|
||||
private final Packet packet;
|
||||
private final GenericFutureListener <? extends Future <? super Void >> [] futureListeners;
|
||||
|
||||
public InboundHandlerTuplePacketListener(Packet inPacket, GenericFutureListener <? extends Future <? super Void >> inFutureListener)
|
||||
{
|
||||
this.packet = inPacket;
|
||||
this.futureListeners = inFutureListener == null ? null : new GenericFutureListener[] {inFutureListener};
|
||||
}
|
||||
}
|
||||
}
|
41
java/src/game/network/NetHandler.java
Executable file
41
java/src/game/network/NetHandler.java
Executable file
|
@ -0,0 +1,41 @@
|
|||
package game.network;
|
||||
|
||||
public abstract class NetHandler {
|
||||
private static final ThreadQuickExitException EXIT = new ThreadQuickExitException();
|
||||
|
||||
public static final class ThreadQuickExitException extends RuntimeException {
|
||||
private ThreadQuickExitException() {
|
||||
this.setStackTrace(new StackTraceElement[0]);
|
||||
}
|
||||
|
||||
public synchronized Throwable fillInStackTrace() {
|
||||
this.setStackTrace(new StackTraceElement[0]);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void onDisconnect(String reason);
|
||||
|
||||
public void update() {
|
||||
}
|
||||
|
||||
public static <T extends NetHandler> void checkThread(final Packet<T> packet, final T handler, IThreadListener listener)
|
||||
throws ThreadQuickExitException {
|
||||
if(!listener.isMainThread()) {
|
||||
listener.schedule(new Runnable() {
|
||||
public void run() {
|
||||
packet.processPacket(handler);
|
||||
}
|
||||
});
|
||||
throw EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends NetHandler> void checkThread(final Packet<T> packet, final T handler, IThreadListener listener, Object check)
|
||||
throws ThreadQuickExitException {
|
||||
if(check == null && listener.isMainThread()) {
|
||||
throw EXIT;
|
||||
}
|
||||
checkThread(packet, handler, listener);
|
||||
}
|
||||
}
|
22
java/src/game/network/NetHandlerHandshakeMemory.java
Executable file
22
java/src/game/network/NetHandlerHandshakeMemory.java
Executable file
|
@ -0,0 +1,22 @@
|
|||
package game.network;
|
||||
|
||||
import game.Server;
|
||||
import game.packet.HPacketHandshake;
|
||||
|
||||
public class NetHandlerHandshakeMemory extends NetHandlerHandshakeServer
|
||||
{
|
||||
private final Server gmServer;
|
||||
private final NetConnection networkManager;
|
||||
|
||||
public NetHandlerHandshakeMemory(Server gmServerIn, NetConnection networkManagerIn)
|
||||
{
|
||||
this.gmServer = gmServerIn;
|
||||
this.networkManager = networkManagerIn;
|
||||
}
|
||||
|
||||
public void processHandshake(HPacketHandshake packetIn)
|
||||
{
|
||||
this.networkManager.setConnectionState(PacketRegistry.LOGIN);
|
||||
this.networkManager.setNetHandler(new NetHandlerLoginServer(this.gmServer, this.networkManager));
|
||||
}
|
||||
}
|
12
java/src/game/network/NetHandlerHandshakeServer.java
Executable file
12
java/src/game/network/NetHandlerHandshakeServer.java
Executable file
|
@ -0,0 +1,12 @@
|
|||
package game.network;
|
||||
|
||||
import game.packet.HPacketHandshake;
|
||||
|
||||
public abstract class NetHandlerHandshakeServer extends NetHandler
|
||||
{
|
||||
public abstract void processHandshake(HPacketHandshake packetIn);
|
||||
|
||||
public void onDisconnect(String reason)
|
||||
{
|
||||
}
|
||||
}
|
41
java/src/game/network/NetHandlerHandshakeTCP.java
Executable file
41
java/src/game/network/NetHandlerHandshakeTCP.java
Executable file
|
@ -0,0 +1,41 @@
|
|||
package game.network;
|
||||
|
||||
import game.Server;
|
||||
import game.init.Config;
|
||||
import game.packet.HPacketHandshake;
|
||||
import game.packet.RPacketDisconnect;
|
||||
|
||||
public class NetHandlerHandshakeTCP extends NetHandlerHandshakeServer
|
||||
{
|
||||
private final Server server;
|
||||
private final NetConnection networkManager;
|
||||
|
||||
public NetHandlerHandshakeTCP(Server serverIn, NetConnection netManager)
|
||||
{
|
||||
this.server = serverIn;
|
||||
this.networkManager = netManager;
|
||||
}
|
||||
|
||||
public void processHandshake(HPacketHandshake packetIn)
|
||||
{
|
||||
if(packetIn.getProtocolVersion() == 0) {
|
||||
this.networkManager.closeChannel("Inkompatibel!");
|
||||
return;
|
||||
}
|
||||
this.networkManager.setConnectionState(PacketRegistry.LOGIN);
|
||||
if (packetIn.getProtocolVersion() != Config.PROTOCOL)
|
||||
{
|
||||
String comp;
|
||||
if(packetIn.getProtocolVersion() < Config.PROTOCOL)
|
||||
comp = "Der Server nutzt eine neuere Version: " + Config.VERSION;
|
||||
else
|
||||
comp = "Der Server nutzt eine ältere Version: " + Config.VERSION;
|
||||
this.networkManager.sendPacket(new RPacketDisconnect(comp));
|
||||
this.networkManager.closeChannel(comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.networkManager.setNetHandler(new NetHandlerLoginServer(this.server, this.networkManager));
|
||||
}
|
||||
}
|
||||
}
|
56
java/src/game/network/NetHandlerLoginClient.java
Executable file
56
java/src/game/network/NetHandlerLoginClient.java
Executable file
|
@ -0,0 +1,56 @@
|
|||
package game.network;
|
||||
|
||||
import game.Game;
|
||||
import game.packet.RPacketDisconnect;
|
||||
import game.packet.RPacketEnableCompression;
|
||||
import game.packet.RPacketLoginSuccess;
|
||||
|
||||
public class NetHandlerLoginClient extends NetHandler {
|
||||
private final Game gm;
|
||||
private final NetConnection networkManager;
|
||||
|
||||
public NetHandlerLoginClient(NetConnection conn, Game gmIn) {
|
||||
this.networkManager = conn;
|
||||
this.gm = gmIn;
|
||||
}
|
||||
|
||||
public void onDisconnect(String reason)
|
||||
{
|
||||
this.gm.disconnected(reason);
|
||||
}
|
||||
|
||||
public final void handleDisconnect(RPacketDisconnect packetIn)
|
||||
{
|
||||
this.networkManager.closeChannel(packetIn.getReason());
|
||||
}
|
||||
|
||||
public void handleLoginSuccess(RPacketLoginSuccess packetIn)
|
||||
{
|
||||
this.networkManager.setConnectionState(PacketRegistry.PLAY);
|
||||
this.networkManager.setNetHandler(new NetHandlerPlayClient(this.gm, this.networkManager));
|
||||
}
|
||||
|
||||
public final void handleEnableCompression(RPacketEnableCompression packetIn)
|
||||
{
|
||||
if (!this.networkManager.isLocalChannel())
|
||||
{
|
||||
this.networkManager.setCompressionTreshold(packetIn.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// public void handlePasswordRequest(RPacketPasswordRequest packetIn) {
|
||||
// if(this.server == null) {
|
||||
// this.networkManager.sendPacket(new LPacketPasswordResponse(this.user, "", ""));
|
||||
// }
|
||||
// else if((packetIn.getPasswordRequested() && this.server.pass.isEmpty()) ||
|
||||
// (packetIn.getPasswordProtected() && this.server.access.isEmpty())) {
|
||||
//// this.toChange = this.gm.getConnected();
|
||||
// this.accessRequired = packetIn.getPasswordProtected() && this.server.access.isEmpty();
|
||||
// this.passwordRequired = packetIn.getPasswordRequested() && this.server.pass.isEmpty();
|
||||
// this.networkManager.closeChannel("");
|
||||
// }
|
||||
// else {
|
||||
// this.networkManager.sendPacket(new LPacketPasswordResponse(this.user, this.access, this.pass));
|
||||
// }
|
||||
// }
|
||||
}
|
147
java/src/game/network/NetHandlerLoginServer.java
Executable file
147
java/src/game/network/NetHandlerLoginServer.java
Executable file
|
@ -0,0 +1,147 @@
|
|||
package game.network;
|
||||
|
||||
import game.Log;
|
||||
import game.Server;
|
||||
import game.color.TextColor;
|
||||
import game.init.Config;
|
||||
import game.init.NameRegistry;
|
||||
import game.packet.LPacketPasswordResponse;
|
||||
import game.packet.RPacketDisconnect;
|
||||
import game.rng.Random;
|
||||
|
||||
public class NetHandlerLoginServer extends NetHandler
|
||||
{
|
||||
private static enum LoginState {
|
||||
PASSWORD, READY_TO_ACCEPT, ACCEPTED;
|
||||
}
|
||||
|
||||
private final Server server;
|
||||
public final NetConnection netManager;
|
||||
|
||||
private LoginState state = LoginState.PASSWORD;
|
||||
private int timer;
|
||||
private String loginUser;
|
||||
private String loginPass;
|
||||
|
||||
public NetHandlerLoginServer(Server server, NetConnection netManager)
|
||||
{
|
||||
this.netManager = netManager;
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public void closeConnection(String reason)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.JNI.info("Trenne " + this.getConnectionInfo());
|
||||
this.netManager.sendPacket(new RPacketDisconnect(reason));
|
||||
this.netManager.closeChannel(reason);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.JNI.error(exception, "Fehler beim Trennen des Spielers beim Login");
|
||||
}
|
||||
}
|
||||
|
||||
public void onDisconnect(String reason)
|
||||
{
|
||||
Log.JNI.info(this.getConnectionInfo() + " wurde beim Login getrennt: " + TextColor.stripCodes(reason));
|
||||
}
|
||||
|
||||
public String getConnectionInfo()
|
||||
{
|
||||
return this.loginUser != null ? (this.loginUser + " (" + this.netManager.getCutAddress()
|
||||
+ ")") : this.netManager.getCutAddress();
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
if(this.state == LoginState.READY_TO_ACCEPT)
|
||||
this.tryAcceptPlayer();
|
||||
// else if (this.currentLoginState == LoginState.DELAY_ACCEPT)
|
||||
// {
|
||||
// if (this.server.getPlayer(this.loginUser) == null)
|
||||
// {
|
||||
// this.currentLoginState = LoginState.ACCEPTED;
|
||||
// this.server.addPlayer(this.networkManager, this.loginUser);
|
||||
// }
|
||||
// }
|
||||
if(this.timer++ == 600)
|
||||
this.closeConnection("Anmeldung dauerte zu lange");
|
||||
}
|
||||
|
||||
private void tryAcceptPlayer()
|
||||
{
|
||||
if(!this.netManager.isLocalChannel()) {
|
||||
// SocketAddress address = this.netManager.getRemoteAddress();
|
||||
// if(this.server.isBanned(address)) {
|
||||
//// Ban ban = this.server.getBanEntryIp(address);
|
||||
// this.closeConnection("Deine IP-Adresse ist von diesem Server gebannt");
|
||||
// return;
|
||||
// }
|
||||
// if(this.server.isBanned(this.loginUser)) {
|
||||
// Ban ban = this.server.getBanEntry(this.loginUser);
|
||||
// this.closeConnection(ban.format(true, 0L));
|
||||
// return;
|
||||
// }
|
||||
if(this.server.getPlayer(this.loginUser) != null) {
|
||||
this.closeConnection("Nutzername '" + this.loginUser + "' ist bereits vergeben.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if (this.server.getPlayer(this.loginUser) != null)
|
||||
// {
|
||||
// this.closeConnection("Nutzername '" + this.loginUser + "' ist bereits vergeben.");
|
||||
// return;
|
||||
//// this.currentLoginState = LoginState.DELAY_ACCEPT;
|
||||
//// player.netHandler.kick("Du hast dich von einen anderen Ort verbunden");
|
||||
// }
|
||||
// this.networkManager.sendPacket(new RPacketLoginSuccess());
|
||||
String kick = this.server.addPlayer(this.netManager, this.loginUser, this.loginPass);
|
||||
if(kick != null)
|
||||
this.closeConnection(kick);
|
||||
else
|
||||
this.state = LoginState.ACCEPTED;
|
||||
}
|
||||
|
||||
// public void processLoginStart(LPacketLoginStart packetIn)
|
||||
// {
|
||||
// if(this.state != LoginState.HELLO)
|
||||
// throw new IllegalStateException("Unerwartetes Start-Paket");
|
||||
// if(!this.netManager.isLocalChannel()) {
|
||||
// this.state = LoginState.PASSWORD;
|
||||
// this.netManager.sendPacket(new RPacketPasswordRequest()); // !Config.password.isEmpty(), Config.auth
|
||||
// }
|
||||
// }
|
||||
|
||||
public void processPasswordResponse(LPacketPasswordResponse packetIn) {
|
||||
if(this.state != LoginState.PASSWORD)
|
||||
throw new IllegalStateException("Unerwartetes Passwort-Paket");
|
||||
this.loginUser = packetIn.getUser();
|
||||
if(this.netManager.isLocalChannel()) {
|
||||
this.loginPass = "";
|
||||
// this.loginUser = Config.localUser;
|
||||
if(this.loginUser.length() > NetHandlerPlayServer.MAX_USER_LENGTH || (!this.loginUser.isEmpty() && !NetHandlerPlayServer.isValidUser(this.loginUser))) {
|
||||
Random rand = new Random();
|
||||
do {
|
||||
this.loginUser = NameRegistry.FANTASY.generate(rand, rand.range(2, 4)).toLowerCase();
|
||||
}
|
||||
while(this.loginUser.length() > NetHandlerPlayServer.MAX_USER_LENGTH || !NetHandlerPlayServer.isValidUser(this.loginUser)); // || this.server.getPlayer(this.loginUser) != null);
|
||||
// this.server.setVar("local_user", this.loginUser);
|
||||
}
|
||||
this.server.setLocalUser(this.loginUser);
|
||||
}
|
||||
else {
|
||||
this.loginPass = packetIn.getPassword();
|
||||
if(this.loginUser.isEmpty() || !NetHandlerPlayServer.isValidUser(this.loginUser))
|
||||
throw new IllegalStateException("Ungültiger Nutzername!");
|
||||
// if(!this.checkConnect(packetIn.getAccess()))
|
||||
// return;
|
||||
if(!Config.password.isEmpty() && !Config.password.equals(packetIn.getAccess())) {
|
||||
this.closeConnection("Falsches Zugangspasswort");
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.state = LoginState.READY_TO_ACCEPT;
|
||||
}
|
||||
}
|
1856
java/src/game/network/NetHandlerPlayClient.java
Executable file
1856
java/src/game/network/NetHandlerPlayClient.java
Executable file
File diff suppressed because it is too large
Load diff
3064
java/src/game/network/NetHandlerPlayServer.java
Executable file
3064
java/src/game/network/NetHandlerPlayServer.java
Executable file
File diff suppressed because it is too large
Load diff
62
java/src/game/network/NettyCompressionDecoder.java
Executable file
62
java/src/game/network/NettyCompressionDecoder.java
Executable file
|
@ -0,0 +1,62 @@
|
|||
package game.network;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
import game.net.buffer.ByteBuf;
|
||||
import game.net.buffer.Unpooled;
|
||||
import game.net.channel.ChannelHandlerContext;
|
||||
import game.net.handler.codec.ByteToMessageDecoder;
|
||||
import game.net.handler.codec.DecoderException;
|
||||
|
||||
public class NettyCompressionDecoder extends ByteToMessageDecoder
|
||||
{
|
||||
private final Inflater inflater;
|
||||
private int treshold;
|
||||
|
||||
public NettyCompressionDecoder(int treshold)
|
||||
{
|
||||
this.treshold = treshold;
|
||||
this.inflater = new Inflater();
|
||||
}
|
||||
|
||||
protected void decode(ChannelHandlerContext p_decode_1_, ByteBuf p_decode_2_, List<Object> p_decode_3_) throws DataFormatException, Exception
|
||||
{
|
||||
if (p_decode_2_.readableBytes() != 0)
|
||||
{
|
||||
PacketBuffer packetbuffer = new PacketBuffer(p_decode_2_);
|
||||
int i = packetbuffer.readVarIntFromBuffer();
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
p_decode_3_.add(packetbuffer.readBytes(packetbuffer.readableBytes()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i < this.treshold)
|
||||
{
|
||||
throw new DecoderException("Badly compressed packet - size of " + i + " is below server threshold of " + this.treshold);
|
||||
}
|
||||
|
||||
if (i > 2097152)
|
||||
{
|
||||
throw new DecoderException("Badly compressed packet - size of " + i + " is larger than protocol maximum of " + 2097152);
|
||||
}
|
||||
|
||||
byte[] abyte = new byte[packetbuffer.readableBytes()];
|
||||
packetbuffer.readBytes(abyte);
|
||||
this.inflater.setInput(abyte);
|
||||
byte[] abyte1 = new byte[i];
|
||||
this.inflater.inflate(abyte1);
|
||||
p_decode_3_.add(Unpooled.wrappedBuffer(abyte1));
|
||||
this.inflater.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setCompressionTreshold(int treshold)
|
||||
{
|
||||
this.treshold = treshold;
|
||||
}
|
||||
}
|
53
java/src/game/network/NettyCompressionEncoder.java
Executable file
53
java/src/game/network/NettyCompressionEncoder.java
Executable file
|
@ -0,0 +1,53 @@
|
|||
package game.network;
|
||||
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import game.net.buffer.ByteBuf;
|
||||
import game.net.channel.ChannelHandlerContext;
|
||||
import game.net.handler.codec.MessageToByteEncoder;
|
||||
|
||||
public class NettyCompressionEncoder extends MessageToByteEncoder<ByteBuf>
|
||||
{
|
||||
private final byte[] buffer = new byte[8192];
|
||||
private final Deflater deflater;
|
||||
private int treshold;
|
||||
|
||||
public NettyCompressionEncoder(int treshold)
|
||||
{
|
||||
this.treshold = treshold;
|
||||
this.deflater = new Deflater();
|
||||
}
|
||||
|
||||
protected void encode(ChannelHandlerContext p_encode_1_, ByteBuf p_encode_2_, ByteBuf p_encode_3_) throws Exception
|
||||
{
|
||||
int i = p_encode_2_.readableBytes();
|
||||
PacketBuffer packetbuffer = new PacketBuffer(p_encode_3_);
|
||||
|
||||
if (i < this.treshold)
|
||||
{
|
||||
packetbuffer.writeVarIntToBuffer(0);
|
||||
packetbuffer.writeBytes(p_encode_2_);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] abyte = new byte[i];
|
||||
p_encode_2_.readBytes(abyte);
|
||||
packetbuffer.writeVarIntToBuffer(abyte.length);
|
||||
this.deflater.setInput(abyte, 0, i);
|
||||
this.deflater.finish();
|
||||
|
||||
while (!this.deflater.finished())
|
||||
{
|
||||
int j = this.deflater.deflate(this.buffer);
|
||||
packetbuffer.writeBytes((byte[])this.buffer, 0, j);
|
||||
}
|
||||
|
||||
this.deflater.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public void setCompressionTreshold(int treshold)
|
||||
{
|
||||
this.treshold = treshold;
|
||||
}
|
||||
}
|
10
java/src/game/network/Packet.java
Executable file
10
java/src/game/network/Packet.java
Executable file
|
@ -0,0 +1,10 @@
|
|||
package game.network;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface Packet<T extends NetHandler>
|
||||
{
|
||||
void readPacketData(PacketBuffer buf) throws IOException;
|
||||
void writePacketData(PacketBuffer buf) throws IOException;
|
||||
void processPacket(T handler);
|
||||
}
|
463
java/src/game/network/PacketBuffer.java
Executable file
463
java/src/game/network/PacketBuffer.java
Executable file
|
@ -0,0 +1,463 @@
|
|||
package game.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import game.init.ItemRegistry;
|
||||
import game.item.ItemStack;
|
||||
import game.nbt.NBTLoader;
|
||||
import game.nbt.NBTSizeTracker;
|
||||
import game.nbt.NBTTagCompound;
|
||||
import game.net.buffer.ByteBuf;
|
||||
import game.net.buffer.ByteBufInputStream;
|
||||
import game.net.buffer.ByteBufOutputStream;
|
||||
import game.net.handler.codec.DecoderException;
|
||||
import game.net.handler.codec.EncoderException;
|
||||
import game.world.BlockPos;
|
||||
|
||||
public class PacketBuffer
|
||||
{
|
||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
|
||||
private final ByteBuf buf;
|
||||
|
||||
public PacketBuffer(ByteBuf wrapped)
|
||||
{
|
||||
this.buf = wrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the number of bytes required to fit the supplied int (0-5) if it were to be read/written using
|
||||
* readVarIntFromBuffer or writeVarIntToBuffer
|
||||
*/
|
||||
public static int getVarIntSize(int input)
|
||||
{
|
||||
for (int i = 1; i < 5; ++i)
|
||||
{
|
||||
if ((input & -1 << i * 7) == 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
public void writeByteArray(byte[] array)
|
||||
{
|
||||
this.writeVarIntToBuffer(array.length);
|
||||
this.writeBytes(array);
|
||||
}
|
||||
|
||||
public byte[] readByteArray()
|
||||
{
|
||||
byte[] abyte = new byte[this.readVarIntFromBuffer()];
|
||||
this.readBytes(abyte);
|
||||
return abyte;
|
||||
}
|
||||
|
||||
public BlockPos readBlockPos()
|
||||
{
|
||||
// return new BlockPos(this.readInt(), this.readInt(), this.readInt());
|
||||
return BlockPos.fromLong(this.readLong());
|
||||
}
|
||||
|
||||
public void writeBlockPos(BlockPos pos)
|
||||
{
|
||||
this.writeLong(pos.toLong());
|
||||
// this.writeInt(pos.getX());
|
||||
// this.writeInt(pos.getY());
|
||||
// this.writeInt(pos.getZ());
|
||||
}
|
||||
|
||||
// public Text readChatComponent() throws IOException
|
||||
// {
|
||||
// return Text.toComponent(this.readNBTTagCompoundFromBuffer());
|
||||
// }
|
||||
//
|
||||
// public void writeChatComponent(Text component) throws IOException
|
||||
// {
|
||||
// this.writeNBTTagCompoundToBuffer(Text.toNbt(component));
|
||||
//// String s = ;
|
||||
//// if(s.length() > 32767) {
|
||||
//// s = component.getFormattedText();
|
||||
//// s = s.length() > 32720 ? s.substring(0, 32720) : s;
|
||||
//// s = TextSerializer.toNbt(new TextComponent(s + ChatFormat.GRAY + ChatFormat.ITALIC + " [...]"));
|
||||
//// }
|
||||
//// this.writeString(s);
|
||||
// }
|
||||
|
||||
public <T extends Enum<T>> T readEnumValue(Class<T> enumClass)
|
||||
{
|
||||
return (T)((Enum[])enumClass.getEnumConstants())[this.readVarIntFromBuffer()];
|
||||
}
|
||||
|
||||
public <T extends Enum<T>> T readEnumOrNull(Class<T> enumClass)
|
||||
{
|
||||
int n = this.readVarIntFromBuffer();
|
||||
return n < 0 ? null : (T)((Enum[])enumClass.getEnumConstants())[n];
|
||||
}
|
||||
|
||||
public void writeEnumValue(Enum<?> value)
|
||||
{
|
||||
this.writeVarIntToBuffer(value.ordinal());
|
||||
}
|
||||
|
||||
public void writeEnumOrNull(Enum<?> value)
|
||||
{
|
||||
this.writeVarIntToBuffer(value == null ? -1 : value.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a compressed int from the buffer. To do so it maximally reads 5 byte-sized chunks whose most significant
|
||||
* bit dictates whether another byte should be read.
|
||||
*/
|
||||
public int readVarIntFromBuffer()
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
byte b0 = this.readByte();
|
||||
i |= (b0 & 127) << j++ * 7;
|
||||
|
||||
if (j > 5)
|
||||
{
|
||||
throw new RuntimeException("VarInt too big");
|
||||
}
|
||||
|
||||
if ((b0 & 128) != 128)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
public long readVarLong()
|
||||
{
|
||||
long i = 0L;
|
||||
int j = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
byte b0 = this.readByte();
|
||||
i |= (long)(b0 & 127) << j++ * 7;
|
||||
|
||||
if (j > 10)
|
||||
{
|
||||
throw new RuntimeException("VarLong too big");
|
||||
}
|
||||
|
||||
if ((b0 & 128) != 128)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// public void writeUuid(UUID uuid)
|
||||
// {
|
||||
// this.writeLong(uuid.getMostSignificantBits());
|
||||
// this.writeLong(uuid.getLeastSignificantBits());
|
||||
// }
|
||||
//
|
||||
// public UUID readUuid()
|
||||
// {
|
||||
// return new UUID(this.readLong(), this.readLong());
|
||||
// }
|
||||
|
||||
/**
|
||||
* Writes a compressed int to the buffer. The smallest number of bytes to fit the passed int will be written. Of
|
||||
* each such byte only 7 bits will be used to describe the actual value since its most significant bit dictates
|
||||
* whether the next byte is part of that same int. Micro-optimization for int values that are expected to have
|
||||
* values below 128.
|
||||
*/
|
||||
public void writeVarIntToBuffer(int input)
|
||||
{
|
||||
while ((input & -128) != 0)
|
||||
{
|
||||
this.writeByte(input & 127 | 128);
|
||||
input >>>= 7;
|
||||
}
|
||||
|
||||
this.writeByte(input);
|
||||
}
|
||||
|
||||
public void writeVarLong(long value)
|
||||
{
|
||||
while ((value & -128L) != 0L)
|
||||
{
|
||||
this.writeByte((int)(value & 127L) | 128);
|
||||
value >>>= 7;
|
||||
}
|
||||
|
||||
this.writeByte((int)value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a compressed NBTTagCompound to this buffer
|
||||
*/
|
||||
public void writeNBTTagCompoundToBuffer(NBTTagCompound nbt)
|
||||
{
|
||||
if (nbt == null)
|
||||
{
|
||||
this.writeByte(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
NBTLoader.write(nbt, new ByteBufOutputStream(this.buf));
|
||||
}
|
||||
catch (IOException ioexception)
|
||||
{
|
||||
throw new EncoderException(ioexception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a compressed NBTTagCompound from this buffer
|
||||
*/
|
||||
public NBTTagCompound readNBTTagCompoundFromBuffer() throws IOException
|
||||
{
|
||||
int i = this.buf.readerIndex();
|
||||
byte b0 = this.readByte();
|
||||
|
||||
if (b0 == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.buf.readerIndex(i);
|
||||
return NBTLoader.read(new ByteBufInputStream(this.buf), new NBTSizeTracker(2097152L));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the ItemStack's ID (short), then size (byte), then damage. (short)
|
||||
*/
|
||||
public void writeItemStackToBuffer(ItemStack stack)
|
||||
{
|
||||
if (stack == null)
|
||||
{
|
||||
this.writeShort(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.writeShort(ItemRegistry.getIdFromItem(stack.getItem()));
|
||||
this.writeVarIntToBuffer(stack.stackSize);
|
||||
this.writeShort(stack.getMetadata());
|
||||
NBTTagCompound nbttagcompound = null;
|
||||
|
||||
if (stack.getItem().isDamageable() || stack.getItem().getShareTag())
|
||||
{
|
||||
nbttagcompound = stack.getTagCompound();
|
||||
}
|
||||
|
||||
this.writeNBTTagCompoundToBuffer(nbttagcompound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an ItemStack from this buffer
|
||||
*/
|
||||
public ItemStack readItemStackFromBuffer() throws IOException
|
||||
{
|
||||
ItemStack itemstack = null;
|
||||
int i = this.readShort();
|
||||
|
||||
if (i >= 0)
|
||||
{
|
||||
int j = this.readVarIntFromBuffer();
|
||||
int k = this.readShort();
|
||||
itemstack = new ItemStack(ItemRegistry.getItemById(i), j, k);
|
||||
itemstack.setTagCompound(this.readNBTTagCompoundFromBuffer());
|
||||
}
|
||||
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a string from this buffer. Expected parameter is maximum allowed string length. Will throw IOException if
|
||||
* string length exceeds this value!
|
||||
*/
|
||||
public String readStringFromBuffer(int maxLength)
|
||||
{
|
||||
int i = this.readVarIntFromBuffer();
|
||||
|
||||
if (i > maxLength * 4)
|
||||
{
|
||||
throw new DecoderException("The received encoded string buffer length is longer than maximum allowed (" + i + " > " + maxLength * 4 + ")");
|
||||
}
|
||||
else if (i < 0)
|
||||
{
|
||||
throw new DecoderException("The received encoded string buffer length is less than zero! Weird string!");
|
||||
}
|
||||
else
|
||||
{
|
||||
String s = new String(this.readBytes(i).array(), UTF_8);
|
||||
|
||||
if (s.length() > maxLength)
|
||||
{
|
||||
throw new DecoderException("The received string length is longer than maximum allowed (" + i + " > " + maxLength + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PacketBuffer writeString(String string)
|
||||
{
|
||||
byte[] abyte = string.getBytes(UTF_8);
|
||||
|
||||
if (abyte.length > 32767)
|
||||
{
|
||||
throw new EncoderException("String too big (was " + string.length() + " bytes encoded, max " + 32767 + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.writeVarIntToBuffer(abyte.length);
|
||||
this.writeBytes(abyte);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public int readableBytes()
|
||||
{
|
||||
return this.buf.readableBytes();
|
||||
}
|
||||
|
||||
public ByteBuf ensureWritable(int p_ensureWritable_1_)
|
||||
{
|
||||
return this.buf.ensureWritable(p_ensureWritable_1_);
|
||||
}
|
||||
|
||||
public boolean readBoolean()
|
||||
{
|
||||
return this.buf.readBoolean();
|
||||
}
|
||||
|
||||
public byte readByte()
|
||||
{
|
||||
return this.buf.readByte();
|
||||
}
|
||||
|
||||
public short readUnsignedByte()
|
||||
{
|
||||
return this.buf.readUnsignedByte();
|
||||
}
|
||||
|
||||
public short readShort()
|
||||
{
|
||||
return this.buf.readShort();
|
||||
}
|
||||
|
||||
public int readUnsignedShort()
|
||||
{
|
||||
return this.buf.readUnsignedShort();
|
||||
}
|
||||
|
||||
public int readInt()
|
||||
{
|
||||
return this.buf.readInt();
|
||||
}
|
||||
|
||||
public long readUnsignedInt()
|
||||
{
|
||||
return this.buf.readUnsignedInt();
|
||||
}
|
||||
|
||||
public long readLong()
|
||||
{
|
||||
return this.buf.readLong();
|
||||
}
|
||||
|
||||
public float readFloat()
|
||||
{
|
||||
return this.buf.readFloat();
|
||||
}
|
||||
|
||||
public double readDouble()
|
||||
{
|
||||
return this.buf.readDouble();
|
||||
}
|
||||
|
||||
public ByteBuf readBytes(int p_readBytes_1_)
|
||||
{
|
||||
return this.buf.readBytes(p_readBytes_1_);
|
||||
}
|
||||
|
||||
public ByteBuf readBytes(byte[] p_readBytes_1_)
|
||||
{
|
||||
return this.buf.readBytes(p_readBytes_1_);
|
||||
}
|
||||
|
||||
public ByteBuf writeBoolean(boolean p_writeBoolean_1_)
|
||||
{
|
||||
return this.buf.writeBoolean(p_writeBoolean_1_);
|
||||
}
|
||||
|
||||
public ByteBuf writeByte(int p_writeByte_1_)
|
||||
{
|
||||
return this.buf.writeByte(p_writeByte_1_);
|
||||
}
|
||||
|
||||
public ByteBuf writeShort(int p_writeShort_1_)
|
||||
{
|
||||
return this.buf.writeShort(p_writeShort_1_);
|
||||
}
|
||||
|
||||
public ByteBuf writeInt(int p_writeInt_1_)
|
||||
{
|
||||
return this.buf.writeInt(p_writeInt_1_);
|
||||
}
|
||||
|
||||
public ByteBuf writeLong(long p_writeLong_1_)
|
||||
{
|
||||
return this.buf.writeLong(p_writeLong_1_);
|
||||
}
|
||||
|
||||
public ByteBuf writeFloat(float p_writeFloat_1_)
|
||||
{
|
||||
return this.buf.writeFloat(p_writeFloat_1_);
|
||||
}
|
||||
|
||||
public ByteBuf writeDouble(double p_writeDouble_1_)
|
||||
{
|
||||
return this.buf.writeDouble(p_writeDouble_1_);
|
||||
}
|
||||
|
||||
public ByteBuf writeBytes(ByteBuf p_writeBytes_1_)
|
||||
{
|
||||
return this.buf.writeBytes(p_writeBytes_1_);
|
||||
}
|
||||
|
||||
public ByteBuf writeBytes(ByteBuf p_writeBytes_1_, int p_writeBytes_2_, int p_writeBytes_3_)
|
||||
{
|
||||
return this.buf.writeBytes(p_writeBytes_1_, p_writeBytes_2_, p_writeBytes_3_);
|
||||
}
|
||||
|
||||
public ByteBuf writeBytes(byte[] p_writeBytes_1_)
|
||||
{
|
||||
return this.buf.writeBytes(p_writeBytes_1_);
|
||||
}
|
||||
|
||||
public ByteBuf writeBytes(byte[] p_writeBytes_1_, int p_writeBytes_2_, int p_writeBytes_3_)
|
||||
{
|
||||
return this.buf.writeBytes(p_writeBytes_1_, p_writeBytes_2_, p_writeBytes_3_);
|
||||
}
|
||||
|
||||
public boolean release()
|
||||
{
|
||||
return this.buf.release();
|
||||
}
|
||||
}
|
51
java/src/game/network/PacketDecoder.java
Executable file
51
java/src/game/network/PacketDecoder.java
Executable file
|
@ -0,0 +1,51 @@
|
|||
package game.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import game.net.buffer.ByteBuf;
|
||||
import game.net.channel.ChannelHandlerContext;
|
||||
import game.net.handler.codec.ByteToMessageDecoder;
|
||||
|
||||
public class PacketDecoder extends ByteToMessageDecoder
|
||||
{
|
||||
private final boolean client;
|
||||
|
||||
public PacketDecoder(boolean client)
|
||||
{
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
protected void decode(ChannelHandlerContext p_decode_1_, ByteBuf p_decode_2_, List<Object> p_decode_3_) throws IOException, InstantiationException, IllegalAccessException, Exception
|
||||
{
|
||||
if (p_decode_2_.readableBytes() != 0)
|
||||
{
|
||||
PacketBuffer packetbuffer = new PacketBuffer(p_decode_2_);
|
||||
int i = packetbuffer.readVarIntFromBuffer();
|
||||
Packet packet = ((PacketRegistry)p_decode_1_.channel().attr(NetConnection.ATTR_STATE).get()).getPacket(this.client, i);
|
||||
|
||||
if (packet == null)
|
||||
{
|
||||
throw new IOException("Ungültige Paket-ID " + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
packet.readPacketData(packetbuffer);
|
||||
|
||||
if (packetbuffer.readableBytes() > 0)
|
||||
{
|
||||
throw new IOException("Paket " + ((PacketRegistry)p_decode_1_.channel().attr(NetConnection.ATTR_STATE).get()).ordinal() + "/" + i + " (" + packet.getClass() + ") war größer als erwartet, " + packetbuffer.readableBytes() + " weitere Bytes wurden beim Lesen von Paket " + i + " gefunden");
|
||||
}
|
||||
else
|
||||
{
|
||||
p_decode_3_.add(packet);
|
||||
|
||||
// if (Log.isTraceEnabled())
|
||||
// {
|
||||
// Log.debug("EIN: [" + p_decode_1_.channel().attr(NetConnection.ATTR_STATE).get() + ":" + i + "] " + packet.getClass().getName());
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
47
java/src/game/network/PacketEncoder.java
Executable file
47
java/src/game/network/PacketEncoder.java
Executable file
|
@ -0,0 +1,47 @@
|
|||
package game.network;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import game.Log;
|
||||
import game.net.buffer.ByteBuf;
|
||||
import game.net.channel.ChannelHandlerContext;
|
||||
import game.net.handler.codec.MessageToByteEncoder;
|
||||
|
||||
public class PacketEncoder extends MessageToByteEncoder<Packet>
|
||||
{
|
||||
private final boolean client;
|
||||
|
||||
public PacketEncoder(boolean client)
|
||||
{
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
protected void encode(ChannelHandlerContext p_encode_1_, Packet p_encode_2_, ByteBuf p_encode_3_) throws IOException, Exception
|
||||
{
|
||||
Integer integer = ((PacketRegistry)p_encode_1_.channel().attr(NetConnection.ATTR_STATE).get()).getId(this.client, p_encode_2_);
|
||||
|
||||
// if (Log.isTraceEnabled())
|
||||
// {
|
||||
// Log.debug("AUS: [" + p_encode_1_.channel().attr(NetConnection.ATTR_STATE).get() + ":" + integer + "] " + p_encode_2_.getClass().getName());
|
||||
// }
|
||||
|
||||
if (integer == null)
|
||||
{
|
||||
throw new IOException("Kann nicht registriertes Paket nicht serialisieren");
|
||||
}
|
||||
else
|
||||
{
|
||||
PacketBuffer packetbuffer = new PacketBuffer(p_encode_3_);
|
||||
packetbuffer.writeVarIntToBuffer(integer.intValue());
|
||||
|
||||
try
|
||||
{
|
||||
p_encode_2_.writePacketData(packetbuffer);
|
||||
}
|
||||
catch (Throwable throwable)
|
||||
{
|
||||
Log.JNI.error(throwable, "Fehler beim Schreiben der Paketdaten");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
26
java/src/game/network/PacketPrepender.java
Executable file
26
java/src/game/network/PacketPrepender.java
Executable file
|
@ -0,0 +1,26 @@
|
|||
package game.network;
|
||||
|
||||
import game.net.buffer.ByteBuf;
|
||||
import game.net.channel.ChannelHandlerContext;
|
||||
import game.net.handler.codec.MessageToByteEncoder;
|
||||
|
||||
public class PacketPrepender extends MessageToByteEncoder<ByteBuf>
|
||||
{
|
||||
protected void encode(ChannelHandlerContext p_encode_1_, ByteBuf p_encode_2_, ByteBuf p_encode_3_) throws Exception
|
||||
{
|
||||
int i = p_encode_2_.readableBytes();
|
||||
int j = PacketBuffer.getVarIntSize(i);
|
||||
|
||||
if (j > 3)
|
||||
{
|
||||
throw new IllegalArgumentException("unable to fit " + i + " into " + 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
PacketBuffer packetbuffer = new PacketBuffer(p_encode_3_);
|
||||
packetbuffer.ensureWritable(j + i);
|
||||
packetbuffer.writeVarIntToBuffer(i);
|
||||
packetbuffer.writeBytes(p_encode_2_, p_encode_2_.readerIndex(), i);
|
||||
}
|
||||
}
|
||||
}
|
252
java/src/game/network/PacketRegistry.java
Executable file
252
java/src/game/network/PacketRegistry.java
Executable file
|
@ -0,0 +1,252 @@
|
|||
package game.network;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import game.collect.BiMap;
|
||||
import game.collect.HashBiMap;
|
||||
import game.collect.Maps;
|
||||
import game.packet.CPacketAction;
|
||||
import game.packet.CPacketBook;
|
||||
import game.packet.CPacketBreak;
|
||||
import game.packet.CPacketCheat;
|
||||
import game.packet.CPacketClick;
|
||||
import game.packet.CPacketComplete;
|
||||
import game.packet.CPacketInput;
|
||||
import game.packet.CPacketKeepAlive;
|
||||
import game.packet.CPacketMessage;
|
||||
import game.packet.CPacketPlace;
|
||||
import game.packet.CPacketPlayer;
|
||||
import game.packet.CPacketSign;
|
||||
import game.packet.CPacketSkin;
|
||||
import game.packet.HPacketHandshake;
|
||||
import game.packet.LPacketPasswordResponse;
|
||||
import game.packet.RPacketDisconnect;
|
||||
import game.packet.RPacketEnableCompression;
|
||||
import game.packet.RPacketLoginSuccess;
|
||||
import game.packet.S14PacketEntity;
|
||||
import game.packet.S18PacketEntityTeleport;
|
||||
import game.packet.S19PacketEntityHeadLook;
|
||||
import game.packet.S1APacketEntityStatus;
|
||||
import game.packet.S1BPacketEntityAttach;
|
||||
import game.packet.S1CPacketEntityMetadata;
|
||||
import game.packet.S1DPacketEntityEffect;
|
||||
import game.packet.S1EPacketRemoveEntityEffect;
|
||||
import game.packet.S20PacketEntityProperties;
|
||||
import game.packet.S27PacketExplosion;
|
||||
import game.packet.S28PacketEffect;
|
||||
import game.packet.S29PacketSoundEffect;
|
||||
import game.packet.S2APacketParticles;
|
||||
import game.packet.S2BPacketChangeGameState;
|
||||
import game.packet.S2CPacketSpawnGlobalEntity;
|
||||
import game.packet.S2DPacketOpenWindow;
|
||||
import game.packet.S2EPacketCloseWindow;
|
||||
import game.packet.S2FPacketSetSlot;
|
||||
import game.packet.S30PacketWindowItems;
|
||||
import game.packet.S31PacketWindowProperty;
|
||||
import game.packet.S32PacketConfirmTransaction;
|
||||
import game.packet.S33PacketUpdateSign;
|
||||
import game.packet.S35PacketUpdateTileEntity;
|
||||
import game.packet.S36PacketSignEditorOpen;
|
||||
import game.packet.S38PacketPlayerListItem;
|
||||
import game.packet.S39PacketPlayerAbilities;
|
||||
import game.packet.S3APacketTabComplete;
|
||||
import game.packet.S43PacketUpdateEntityNBT;
|
||||
import game.packet.SPacketAnimation;
|
||||
import game.packet.SPacketBiomes;
|
||||
import game.packet.SPacketBlockAction;
|
||||
import game.packet.SPacketBlockBreakAnim;
|
||||
import game.packet.SPacketBlockChange;
|
||||
import game.packet.SPacketCamera;
|
||||
import game.packet.SPacketChunkData;
|
||||
import game.packet.SPacketCollectItem;
|
||||
import game.packet.SPacketDestroyEntities;
|
||||
import game.packet.SPacketDimensionName;
|
||||
import game.packet.SPacketDisconnect;
|
||||
import game.packet.SPacketEntityEquipment;
|
||||
import game.packet.SPacketEntityVelocity;
|
||||
import game.packet.SPacketHeldItemChange;
|
||||
import game.packet.SPacketJoinGame;
|
||||
import game.packet.SPacketKeepAlive;
|
||||
import game.packet.SPacketMapChunkBulk;
|
||||
import game.packet.SPacketMessage;
|
||||
import game.packet.SPacketMultiBlockChange;
|
||||
import game.packet.SPacketPlayerPosLook;
|
||||
import game.packet.SPacketRespawn;
|
||||
import game.packet.SPacketSetExperience;
|
||||
import game.packet.SPacketSkin;
|
||||
import game.packet.SPacketSpawnMob;
|
||||
import game.packet.SPacketSpawnObject;
|
||||
import game.packet.SPacketSpawnPlayer;
|
||||
import game.packet.SPacketTimeUpdate;
|
||||
import game.packet.SPacketTrades;
|
||||
import game.packet.SPacketUpdateHealth;
|
||||
import game.packet.SPacketWorld;
|
||||
|
||||
public enum PacketRegistry
|
||||
{
|
||||
HANDSHAKE
|
||||
{
|
||||
{
|
||||
this.client(HPacketHandshake.class);
|
||||
}
|
||||
},
|
||||
LOGIN
|
||||
{
|
||||
{
|
||||
this.server(RPacketDisconnect.class);
|
||||
this.server(RPacketLoginSuccess.class);
|
||||
this.server(RPacketEnableCompression.class);
|
||||
// this.server(RPacketPasswordRequest.class);
|
||||
// this.client(LPacketLoginStart.class);
|
||||
this.client(LPacketPasswordResponse.class);
|
||||
}
|
||||
},
|
||||
PLAY
|
||||
{
|
||||
{
|
||||
this.server(SPacketKeepAlive.class);
|
||||
this.server(SPacketJoinGame.class);
|
||||
this.server(SPacketMessage.class);
|
||||
// this.server(SPacketMessage.class);
|
||||
this.server(SPacketTimeUpdate.class);
|
||||
this.server(SPacketEntityEquipment.class);
|
||||
this.server(SPacketUpdateHealth.class);
|
||||
this.server(SPacketRespawn.class);
|
||||
this.server(SPacketPlayerPosLook.class);
|
||||
this.server(SPacketHeldItemChange.class);
|
||||
this.server(SPacketAnimation.class);
|
||||
this.server(SPacketSpawnPlayer.class);
|
||||
this.server(SPacketCollectItem.class);
|
||||
this.server(SPacketSpawnObject.class);
|
||||
this.server(SPacketSpawnMob.class);
|
||||
// this.server(SPacketSpawnPainting.class);
|
||||
// this.server(SPacketSpawnExperienceOrb.class);
|
||||
this.server(SPacketEntityVelocity.class);
|
||||
this.server(SPacketDestroyEntities.class);
|
||||
this.server(S14PacketEntity.class);
|
||||
this.server(S14PacketEntity.S15PacketEntityRelMove.class);
|
||||
this.server(S14PacketEntity.S16PacketEntityLook.class);
|
||||
this.server(S14PacketEntity.S17PacketEntityLookMove.class);
|
||||
this.server(S18PacketEntityTeleport.class);
|
||||
this.server(S19PacketEntityHeadLook.class);
|
||||
this.server(S1APacketEntityStatus.class);
|
||||
this.server(S1BPacketEntityAttach.class);
|
||||
this.server(S1CPacketEntityMetadata.class);
|
||||
this.server(S1DPacketEntityEffect.class);
|
||||
this.server(S1EPacketRemoveEntityEffect.class);
|
||||
this.server(SPacketSetExperience.class);
|
||||
this.server(S20PacketEntityProperties.class);
|
||||
this.server(SPacketChunkData.class);
|
||||
this.server(SPacketMultiBlockChange.class);
|
||||
this.server(SPacketBlockChange.class);
|
||||
this.server(SPacketBlockAction.class);
|
||||
this.server(SPacketBlockBreakAnim.class);
|
||||
this.server(SPacketMapChunkBulk.class);
|
||||
this.server(S27PacketExplosion.class);
|
||||
this.server(S28PacketEffect.class);
|
||||
this.server(S29PacketSoundEffect.class);
|
||||
this.server(S2APacketParticles.class);
|
||||
this.server(S2BPacketChangeGameState.class);
|
||||
this.server(S2CPacketSpawnGlobalEntity.class);
|
||||
this.server(S2DPacketOpenWindow.class);
|
||||
this.server(S2EPacketCloseWindow.class);
|
||||
this.server(S2FPacketSetSlot.class);
|
||||
this.server(S30PacketWindowItems.class);
|
||||
this.server(S31PacketWindowProperty.class);
|
||||
this.server(S32PacketConfirmTransaction.class);
|
||||
this.server(S33PacketUpdateSign.class);
|
||||
// this.server(S34PacketMaps.class);
|
||||
this.server(S35PacketUpdateTileEntity.class);
|
||||
this.server(S36PacketSignEditorOpen.class);
|
||||
// this.server(S37PacketStatistics.class);
|
||||
this.server(S38PacketPlayerListItem.class);
|
||||
this.server(S39PacketPlayerAbilities.class);
|
||||
this.server(S3APacketTabComplete.class);
|
||||
// this.server(SPacketDisplay.class);
|
||||
this.server(SPacketSkin.class);
|
||||
this.server(SPacketDisconnect.class);
|
||||
this.server(SPacketWorld.class);
|
||||
// this.server(SPacketCapes.class);
|
||||
this.server(SPacketCamera.class);
|
||||
this.server(SPacketBiomes.class);
|
||||
// this.server(S42PacketTitle.class);
|
||||
this.server(S43PacketUpdateEntityNBT.class);
|
||||
// this.server(SPacketBook.class);
|
||||
this.server(SPacketTrades.class);
|
||||
// this.server(SPacketNotify.class);
|
||||
this.server(SPacketDimensionName.class);
|
||||
|
||||
this.client(CPacketKeepAlive.class);
|
||||
this.client(CPacketMessage.class);
|
||||
this.client(CPacketAction.class);
|
||||
this.client(CPacketPlayer.class);
|
||||
this.client(CPacketPlayer.C04PacketPlayerPosition.class);
|
||||
this.client(CPacketPlayer.C05PacketPlayerLook.class);
|
||||
this.client(CPacketPlayer.C06PacketPlayerPosLook.class);
|
||||
this.client(CPacketBreak.class);
|
||||
this.client(CPacketPlace.class);
|
||||
this.client(CPacketInput.class);
|
||||
this.client(CPacketClick.class);
|
||||
this.client(CPacketCheat.class);
|
||||
this.client(CPacketComplete.class);
|
||||
this.client(CPacketSkin.class);
|
||||
this.client(CPacketSign.class);
|
||||
this.client(CPacketBook.class);
|
||||
// this.client(CPacketCmdBlock.class);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Map<Class<? extends Packet>, PacketRegistry> STATES = Maps.<Class<? extends Packet>, PacketRegistry>newHashMap();
|
||||
|
||||
private final BiMap<Integer, Class<? extends Packet>> server = HashBiMap.<Integer, Class<? extends Packet>>create();
|
||||
private final BiMap<Integer, Class<? extends Packet>> client = HashBiMap.<Integer, Class<? extends Packet>>create();
|
||||
|
||||
protected void server(Class <? extends Packet > clazz)
|
||||
{
|
||||
if(this.server.containsValue(clazz))
|
||||
throw new IllegalArgumentException("S-Paket " + clazz + " ist bereits bekannt unter ID " + this.server.inverse().get(clazz));
|
||||
this.server.put(Integer.valueOf(this.server.size()), clazz);
|
||||
}
|
||||
|
||||
protected void client(Class <? extends Packet > clazz)
|
||||
{
|
||||
if(this.client.containsValue(clazz))
|
||||
throw new IllegalArgumentException("C-Paket " + clazz + " ist bereits bekannt unter ID " + this.client.inverse().get(clazz));
|
||||
this.client.put(Integer.valueOf(this.client.size()), clazz);
|
||||
}
|
||||
|
||||
public Integer getId(boolean client, Packet packet)
|
||||
{
|
||||
return (client ? this.client : this.server).inverse().get(packet.getClass());
|
||||
}
|
||||
|
||||
public Packet getPacket(boolean client, int id) throws InstantiationException, IllegalAccessException {
|
||||
Class<? extends Packet> oclass = (client ? this.client : this.server).get(id);
|
||||
return oclass == null ? null : oclass.newInstance();
|
||||
}
|
||||
|
||||
public static PacketRegistry getType(Packet packetIn)
|
||||
{
|
||||
return STATES.get(packetIn.getClass());
|
||||
}
|
||||
|
||||
static {
|
||||
for(PacketRegistry reg : values()) {
|
||||
for(BiMap<Integer, Class<? extends Packet>> map : new BiMap[] {reg.server, reg.client}) {
|
||||
for(Class<? extends Packet> clazz : map.values()) {
|
||||
if(STATES.containsKey(clazz) && STATES.get(clazz) != reg) {
|
||||
throw new Error("Paket " + clazz + " ist bereits zu ID " + STATES.get(clazz)
|
||||
+ " zugewiesen - kann nicht auf " + reg + " neu zuweisen");
|
||||
}
|
||||
try {
|
||||
clazz.newInstance();
|
||||
}
|
||||
catch(Throwable e) {
|
||||
throw new Error("Paket " + clazz + " kann nicht instanziert werden!");
|
||||
}
|
||||
STATES.put(clazz, reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
55
java/src/game/network/PacketSplitter.java
Executable file
55
java/src/game/network/PacketSplitter.java
Executable file
|
@ -0,0 +1,55 @@
|
|||
package game.network;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import game.net.buffer.ByteBuf;
|
||||
import game.net.buffer.Unpooled;
|
||||
import game.net.channel.ChannelHandlerContext;
|
||||
import game.net.handler.codec.ByteToMessageDecoder;
|
||||
import game.net.handler.codec.CorruptedFrameException;
|
||||
|
||||
public class PacketSplitter extends ByteToMessageDecoder
|
||||
{
|
||||
protected void decode(ChannelHandlerContext p_decode_1_, ByteBuf p_decode_2_, List<Object> p_decode_3_) throws Exception
|
||||
{
|
||||
p_decode_2_.markReaderIndex();
|
||||
byte[] abyte = new byte[3];
|
||||
|
||||
for (int i = 0; i < abyte.length; ++i)
|
||||
{
|
||||
if (!p_decode_2_.isReadable())
|
||||
{
|
||||
p_decode_2_.resetReaderIndex();
|
||||
return;
|
||||
}
|
||||
|
||||
abyte[i] = p_decode_2_.readByte();
|
||||
|
||||
if (abyte[i] >= 0)
|
||||
{
|
||||
PacketBuffer packetbuffer = new PacketBuffer(Unpooled.wrappedBuffer(abyte));
|
||||
|
||||
try
|
||||
{
|
||||
int j = packetbuffer.readVarIntFromBuffer();
|
||||
|
||||
if (p_decode_2_.readableBytes() >= j)
|
||||
{
|
||||
p_decode_3_.add(p_decode_2_.readBytes(j));
|
||||
return;
|
||||
}
|
||||
|
||||
p_decode_2_.resetReaderIndex();
|
||||
}
|
||||
finally
|
||||
{
|
||||
packetbuffer.release();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new CorruptedFrameException("length wider than 21-bit");
|
||||
}
|
||||
}
|
603
java/src/game/network/PlayerController.java
Executable file
603
java/src/game/network/PlayerController.java
Executable file
|
@ -0,0 +1,603 @@
|
|||
package game.network;
|
||||
|
||||
import game.Game;
|
||||
import game.audio.PositionedSound;
|
||||
import game.block.Block;
|
||||
import game.entity.Entity;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.init.BlockRegistry;
|
||||
import game.init.EntityRegistry;
|
||||
import game.item.ItemBlock;
|
||||
import game.item.ItemControl;
|
||||
import game.item.ItemStack;
|
||||
import game.material.Material;
|
||||
import game.packet.CPacketAction;
|
||||
import game.packet.CPacketBreak;
|
||||
import game.packet.CPacketClick;
|
||||
import game.packet.CPacketPlace;
|
||||
import game.world.BlockPos;
|
||||
import game.world.Facing;
|
||||
import game.world.State;
|
||||
import game.world.Vec3;
|
||||
import game.world.World;
|
||||
import game.world.WorldClient;
|
||||
|
||||
public class PlayerController
|
||||
{
|
||||
private final Game gm;
|
||||
private final NetHandlerPlayClient netClientHandler;
|
||||
private BlockPos currentBlock = new BlockPos(-1, -1, -1);
|
||||
private ItemStack currentItemHittingBlock;
|
||||
private float curBlockDamageMP;
|
||||
private float stepSoundTickCounter;
|
||||
private int blockHitDelay;
|
||||
private boolean isHittingBlock;
|
||||
private boolean noclip;
|
||||
private int currentPlayerItem;
|
||||
private boolean interacting;
|
||||
|
||||
public PlayerController(Game gmIn, NetHandlerPlayClient netHandler)
|
||||
{
|
||||
this.gm = gmIn;
|
||||
this.netClientHandler = netHandler;
|
||||
}
|
||||
|
||||
// public static void clickBlockCreative(Game gmIn, PlayerController playerController, BlockPos pos, Facing facing)
|
||||
// {
|
||||
// if (!gmIn.theWorld.extinguishFire(gmIn.thePlayer, pos, facing))
|
||||
// {
|
||||
// playerController.onPlayerDestroyBlock(pos, facing);
|
||||
// }
|
||||
// }
|
||||
|
||||
// public void setPlayerCapabilities()
|
||||
// {
|
||||
// this.gm.thePlayer.flying &= this.gm.thePlayer.hasEffect(Potion.flying) || this.gm.thePlayer.noclip;
|
||||
// }
|
||||
|
||||
// public boolean isNoclip()
|
||||
// {
|
||||
// return this.gm.thePlayer.capabilities.noClip;
|
||||
// }
|
||||
|
||||
// public void setNoclip(boolean noclip)
|
||||
// {
|
||||
// this.noclip = noclip;
|
||||
// }
|
||||
|
||||
// public void setCheat(boolean cheat)
|
||||
// {
|
||||
// this.cheat = cheat;
|
||||
// this.setPlayerCapabilities();
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// public boolean shouldDrawHUD()
|
||||
// {
|
||||
// return !this.creative;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Called when a player completes the destruction of a block
|
||||
*/
|
||||
public boolean onPlayerDestroyBlock(BlockPos pos, Facing side)
|
||||
{
|
||||
// if (this.gamemode.isAdventure())
|
||||
// {
|
||||
// if (this.gamemode == Gamemode.SPECTATOR)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if (!this.gm.thePlayer.isAllowEdit())
|
||||
// {
|
||||
// Block block = this.gm.theWorld.getBlockState(pos).getBlock();
|
||||
// ItemStack itemstack = this.gm.thePlayer.getCurrentEquippedItem();
|
||||
//
|
||||
// if (itemstack == null)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// if (!itemstack.canDestroy(block))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (this.gm.thePlayer.getHeldItem() != null && !this.gm.thePlayer.getHeldItem().getItem().canBreakBlocks())
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
World world = this.gm.theWorld;
|
||||
State iblockstate = world.getState(pos);
|
||||
Block block1 = iblockstate.getBlock();
|
||||
|
||||
if (block1.getMaterial() == Material.air)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
world.playAuxSFX(2001, pos, BlockRegistry.getStateId(iblockstate));
|
||||
boolean flag = world.setBlockToAir(pos);
|
||||
|
||||
if (flag)
|
||||
{
|
||||
block1.onBlockDestroyedByPlayer(world, pos, iblockstate);
|
||||
}
|
||||
|
||||
this.currentBlock = new BlockPos(this.currentBlock.getX(), -1, this.currentBlock.getZ());
|
||||
|
||||
// if (!this.creative)
|
||||
// {
|
||||
ItemStack itemstack1 = this.gm.thePlayer.getCurrentEquippedItem();
|
||||
|
||||
if (itemstack1 != null)
|
||||
{
|
||||
itemstack1.onBlockDestroyed(world, block1, pos, this.gm.thePlayer);
|
||||
|
||||
if (itemstack1.stackSize == 0)
|
||||
{
|
||||
this.gm.thePlayer.destroyCurrentEquippedItem();
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
return flag;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the player is hitting a block with an item.
|
||||
*/
|
||||
public boolean clickBlock(BlockPos loc, Facing face)
|
||||
{
|
||||
// if (this.gamemode.isAdventure())
|
||||
// {
|
||||
// if (this.gamemode == Gamemode.SPECTATOR)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if (!this.gm.thePlayer.isAllowEdit())
|
||||
// {
|
||||
// Block block = this.gm.theWorld.getBlockState(loc).getBlock();
|
||||
// ItemStack itemstack = this.gm.thePlayer.getCurrentEquippedItem();
|
||||
//
|
||||
// if (itemstack == null)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// if (!itemstack.canDestroy(block))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!World.isValidXZ(loc))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemStack stack = this.gm.thePlayer.getHeldItem();
|
||||
if(stack != null && stack.getItem().onAction(stack, this.gm.thePlayer, this.gm.theWorld, ItemControl.PRIMARY, loc)) {
|
||||
this.interacting = true;
|
||||
this.netClientHandler.addToSendQueue(new CPacketBreak(CPacketBreak.Action.START_DESTROY_BLOCK, loc, face));
|
||||
return true;
|
||||
}
|
||||
// if (this.creative)
|
||||
// {
|
||||
// this.netClientHandler.addToSendQueue(new CPacketBreak(CPacketBreak.Action.START_DESTROY_BLOCK, loc, face));
|
||||
// clickBlockCreative(this.gm, this, loc, face);
|
||||
// this.blockHitDelay = 5;
|
||||
// }
|
||||
// else
|
||||
if (!this.isHittingBlock || !this.isHittingPosition(loc))
|
||||
{
|
||||
if (this.isHittingBlock)
|
||||
{
|
||||
this.netClientHandler.addToSendQueue(new CPacketBreak(CPacketBreak.Action.ABORT_DESTROY_BLOCK, this.currentBlock, face));
|
||||
}
|
||||
|
||||
this.netClientHandler.addToSendQueue(new CPacketBreak(CPacketBreak.Action.START_DESTROY_BLOCK, loc, face));
|
||||
Block block1 = this.gm.theWorld.getState(loc).getBlock();
|
||||
boolean flag = block1.getMaterial() != Material.air;
|
||||
|
||||
if (flag && this.curBlockDamageMP == 0.0F)
|
||||
{
|
||||
block1.onBlockClicked(this.gm.theWorld, loc, this.gm.thePlayer);
|
||||
}
|
||||
|
||||
if (flag && block1.getPlayerRelativeBlockHardness(this.gm.thePlayer, this.gm.thePlayer.worldObj, loc) >= 1.0F)
|
||||
{
|
||||
this.onPlayerDestroyBlock(loc, face);
|
||||
// if(this.cheat && block1.getPlayerRelativeBlockHardness(this.gm.thePlayer, this.gm.thePlayer.worldObj, loc) < 1.0F)
|
||||
this.blockHitDelay = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.isHittingBlock = true;
|
||||
this.currentBlock = loc;
|
||||
this.currentItemHittingBlock = this.gm.thePlayer.getHeldItem();
|
||||
this.curBlockDamageMP = 0.0F;
|
||||
this.stepSoundTickCounter = 0.0F;
|
||||
this.gm.theWorld.sendBlockBreakProgress(this.gm.thePlayer.getId(), this.currentBlock, (int)(this.curBlockDamageMP * 10.0F) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets current block damage and isHittingBlock
|
||||
*/
|
||||
public void resetBlockRemoving()
|
||||
{
|
||||
if (this.isHittingBlock)
|
||||
{
|
||||
this.netClientHandler.addToSendQueue(new CPacketBreak(CPacketBreak.Action.ABORT_DESTROY_BLOCK, this.currentBlock, Facing.DOWN));
|
||||
this.isHittingBlock = false;
|
||||
this.curBlockDamageMP = 0.0F;
|
||||
this.gm.theWorld.sendBlockBreakProgress(this.gm.thePlayer.getId(), this.currentBlock, -1);
|
||||
}
|
||||
}
|
||||
|
||||
public void resetInteraction()
|
||||
{
|
||||
this.interacting = false;
|
||||
}
|
||||
|
||||
public boolean onPlayerDamageBlock(BlockPos posBlock, Facing directionFacing)
|
||||
{
|
||||
if(this.interacting)
|
||||
return false;
|
||||
this.syncCurrentPlayItem();
|
||||
|
||||
if (this.blockHitDelay > 0)
|
||||
{
|
||||
--this.blockHitDelay;
|
||||
return true;
|
||||
}
|
||||
// else if (this.creative && World.isValidXZ(posBlock))
|
||||
// {
|
||||
// this.blockHitDelay = 5;
|
||||
// this.netClientHandler.addToSendQueue(new CPacketBreak(CPacketBreak.Action.START_DESTROY_BLOCK, posBlock, directionFacing));
|
||||
// clickBlockCreative(this.gm, this, posBlock, directionFacing);
|
||||
// return true;
|
||||
// }
|
||||
else if (this.isHittingPosition(posBlock))
|
||||
{
|
||||
Block block = this.gm.theWorld.getState(posBlock).getBlock();
|
||||
|
||||
if (block.getMaterial() == Material.air)
|
||||
{
|
||||
this.isHittingBlock = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.curBlockDamageMP += block.getPlayerRelativeBlockHardness(this.gm.thePlayer, this.gm.thePlayer.worldObj, posBlock);
|
||||
|
||||
if (this.stepSoundTickCounter % 4.0F == 0.0F && block.sound.getStepSound() != null)
|
||||
{
|
||||
this.gm.getSoundManager().playSound(new PositionedSound(block.sound.getStepSound(), (block.sound.getVolume() + 1.0F) / 8.0F, /* block.sound.getFrequency() * 0.5F, */ (float)posBlock.getX() + 0.5F, (float)posBlock.getY() + 0.5F, (float)posBlock.getZ() + 0.5F));
|
||||
}
|
||||
|
||||
++this.stepSoundTickCounter;
|
||||
|
||||
if (this.curBlockDamageMP >= 1.0F)
|
||||
{
|
||||
this.isHittingBlock = false;
|
||||
this.netClientHandler.addToSendQueue(new CPacketBreak(CPacketBreak.Action.STOP_DESTROY_BLOCK, posBlock, directionFacing));
|
||||
this.onPlayerDestroyBlock(posBlock, directionFacing);
|
||||
this.curBlockDamageMP = 0.0F;
|
||||
this.stepSoundTickCounter = 0.0F;
|
||||
this.blockHitDelay = 5;
|
||||
}
|
||||
|
||||
this.gm.theWorld.sendBlockBreakProgress(this.gm.thePlayer.getId(), this.currentBlock, (int)(this.curBlockDamageMP * 10.0F) - 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.clickBlock(posBlock, directionFacing);
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * player reach distance = 4F
|
||||
// */
|
||||
// public float getBlockReachDistance()
|
||||
// {
|
||||
// return ;
|
||||
// }
|
||||
|
||||
public void updateController()
|
||||
{
|
||||
this.syncCurrentPlayItem();
|
||||
|
||||
if (this.netClientHandler.getNetworkManager().isChannelOpen())
|
||||
{
|
||||
this.netClientHandler.getNetworkManager().processReceivedPackets();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.netClientHandler.getNetworkManager().checkDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isHittingPosition(BlockPos pos)
|
||||
{
|
||||
ItemStack itemstack = this.gm.thePlayer.getHeldItem();
|
||||
boolean flag = this.currentItemHittingBlock == null && itemstack == null;
|
||||
|
||||
if (this.currentItemHittingBlock != null && itemstack != null)
|
||||
{
|
||||
flag = itemstack.getItem() == this.currentItemHittingBlock.getItem() && ItemStack.areItemStackTagsEqual(itemstack, this.currentItemHittingBlock) && (itemstack.isItemStackDamageable() || itemstack.getMetadata() == this.currentItemHittingBlock.getMetadata());
|
||||
}
|
||||
|
||||
return pos.equals(this.currentBlock) && flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs the current player item with the server
|
||||
*/
|
||||
private void syncCurrentPlayItem()
|
||||
{
|
||||
int i = this.gm.thePlayer.inventory.currentItem;
|
||||
|
||||
if (i != this.currentPlayerItem)
|
||||
{
|
||||
this.currentPlayerItem = i;
|
||||
this.netClientHandler.addToSendQueue(new CPacketAction(CPacketAction.Action.SET_ITEMSLOT, this.currentPlayerItem));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onPlayerRightClick(EntityNPC player, WorldClient worldIn, ItemStack heldStack, BlockPos hitPos, Facing side, Vec3 hitVec)
|
||||
{
|
||||
this.syncCurrentPlayItem();
|
||||
float f = (float)(hitVec.xCoord - (double)hitPos.getX());
|
||||
float f1 = (float)(hitVec.yCoord - (double)hitPos.getY());
|
||||
float f2 = (float)(hitVec.zCoord - (double)hitPos.getZ());
|
||||
boolean flag = false;
|
||||
|
||||
if (!World.isValidXZ(hitPos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(heldStack == null || !heldStack.getItem().onAction(heldStack, player, worldIn, ItemControl.SECONDARY, hitPos)) {
|
||||
// if (this.gamemode != Gamemode.SPECTATOR)
|
||||
// {
|
||||
State iblockstate = worldIn.getState(hitPos);
|
||||
|
||||
if ((!player.isSneaking() || player.getHeldItem() == null) // && (player.getHeldItem() == null || !player.getHeldItem().getItem().ignoresBlocks())
|
||||
&& iblockstate.getBlock().onBlockActivated(worldIn, hitPos, iblockstate, player, side, f, f1, f2))
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (!flag && heldStack != null && heldStack.getItem() instanceof ItemBlock)
|
||||
{
|
||||
ItemBlock itemblock = (ItemBlock)heldStack.getItem();
|
||||
|
||||
if (!itemblock.canPlaceBlockOnSide(worldIn, hitPos, side, player, heldStack))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
else {
|
||||
heldStack.getItem().onItemUse(heldStack, player, worldIn, hitPos, side, f, f1, f2);
|
||||
flag = true;
|
||||
}
|
||||
|
||||
this.netClientHandler.addToSendQueue(new CPacketPlace(hitPos, side.getIndex(), player.inventory.getCurrentItem(), f, f1, f2));
|
||||
|
||||
if (!flag) // && this.gamemode != Gamemode.SPECTATOR)
|
||||
{
|
||||
if (heldStack == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// else if (this.creative)
|
||||
// {
|
||||
// int i = heldStack.getMetadata();
|
||||
// int j = heldStack.stackSize;
|
||||
// boolean flag1 = heldStack.onItemUse(player, worldIn, hitPos, side, f, f1, f2);
|
||||
// heldStack.setItemDamage(i);
|
||||
// heldStack.stackSize = j;
|
||||
// return flag1;
|
||||
// }
|
||||
else
|
||||
{
|
||||
return heldStack.onItemUse(player, worldIn, hitPos, side, f, f1, f2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the server of things like consuming food, etc...
|
||||
*/
|
||||
public boolean sendUseItem(EntityNPC playerIn, World worldIn, ItemStack itemStackIn)
|
||||
{
|
||||
// if (this.gamemode == Gamemode.SPECTATOR)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
this.syncCurrentPlayItem();
|
||||
this.netClientHandler.addToSendQueue(new CPacketPlace(playerIn.inventory.getCurrentItem()));
|
||||
int i = itemStackIn.stackSize;
|
||||
ItemStack itemstack = itemStackIn.useItemRightClick(worldIn, playerIn);
|
||||
|
||||
if (itemstack != itemStackIn || itemstack != null && itemstack.stackSize != i)
|
||||
{
|
||||
playerIn.inventory.mainInventory[playerIn.inventory.currentItem] = itemstack;
|
||||
|
||||
if (itemstack.stackSize == 0)
|
||||
{
|
||||
playerIn.inventory.mainInventory[playerIn.inventory.currentItem] = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
public EntityNPC createPlayerEntity(WorldClient worldIn, int type)
|
||||
{
|
||||
EntityNPC player = (EntityNPC)EntityRegistry.createEntityByID(type, worldIn);
|
||||
player.setClientPlayer(this.gm, this.netClientHandler);
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attacks an entity
|
||||
*/
|
||||
public void attackEntity(EntityNPC playerIn, Entity targetEntity)
|
||||
{
|
||||
this.syncCurrentPlayItem();
|
||||
this.netClientHandler.addToSendQueue(new CPacketAction(CPacketAction.Action.ATTACK, targetEntity.getId()));
|
||||
|
||||
// if (this.gamemode != Gamemode.SPECTATOR)
|
||||
// {
|
||||
playerIn.attackTargetEntityWithCurrentItem(targetEntity);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Send packet to server - player is interacting with another entity (left click)
|
||||
*/
|
||||
public boolean interactWithEntitySendPacket(EntityNPC playerIn, Entity targetEntity)
|
||||
{
|
||||
this.syncCurrentPlayItem();
|
||||
this.netClientHandler.addToSendQueue(new CPacketAction(CPacketAction.Action.INTERACT, targetEntity.getId()));
|
||||
return /* this.gamemode != Gamemode.SPECTATOR && */ playerIn.interactWith(targetEntity);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Return true when the player rightclick on an entity
|
||||
// *
|
||||
// * @param player The player's instance
|
||||
// * @param entityIn The entity clicked
|
||||
// * @param movingObject The object clicked
|
||||
// */
|
||||
// public boolean isPlayerRightClickingOnEntity(EntityNPC player, Entity entityIn, MovingObjectPosition movingObject)
|
||||
// {
|
||||
// this.syncCurrentPlayItem();
|
||||
// Vec3 vec3 = new Vec3(movingObject.hitVec.xCoord - entityIn.posX, movingObject.hitVec.yCoord - entityIn.posY, movingObject.hitVec.zCoord - entityIn.posZ);
|
||||
// this.netClientHandler.addToSendQueue(new C02PacketUseEntity(entityIn, vec3));
|
||||
// return this.gamemode != Gamemode.SPECTATOR && entityIn.interactAt(player, vec3);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Handles slot clicks sends a packet to the server.
|
||||
*/
|
||||
public ItemStack windowClick(int windowId, int slotId, int mouseButtonClicked, int mode, EntityNPC playerIn)
|
||||
{
|
||||
short short1 = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
|
||||
ItemStack itemstack = playerIn.openContainer.slotClick(slotId, mouseButtonClicked, mode, playerIn);
|
||||
this.netClientHandler.addToSendQueue(new CPacketClick(windowId, slotId, mouseButtonClicked, mode, itemstack, short1));
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
/**
|
||||
* GuiEnchantment uses this during multiplayer to tell PlayerControllerMP to send a packet indicating the
|
||||
* enchantment action the player has taken.
|
||||
*
|
||||
* @param windowID The ID of the current window
|
||||
* @param button The button id (enchantment selected)
|
||||
*/
|
||||
public void sendEnchantPacket(int windowID, int button)
|
||||
{
|
||||
this.netClientHandler.addToSendQueue(new CPacketAction(CPacketAction.Action.ENCHANT_ITEM, windowID | (button << 8)));
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Used in PlayerControllerMP to update the server with an ItemStack in a slot.
|
||||
// */
|
||||
// public void sendCheatPacket(ItemStack itemStackIn, boolean full)
|
||||
// {
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Sends a Packet107 to the server to drop the item on the ground
|
||||
// */
|
||||
// public void sendPacketDropItem(ItemStack itemStackIn)
|
||||
// {
|
||||
// if (this.creative && itemStackIn != null)
|
||||
// {
|
||||
// this.netClientHandler.addToSendQueue(new CPacketCreative(-1, itemStackIn));
|
||||
// }
|
||||
// }
|
||||
|
||||
public void onStoppedUsingItem(EntityNPC playerIn)
|
||||
{
|
||||
this.syncCurrentPlayItem();
|
||||
this.netClientHandler.addToSendQueue(new CPacketBreak(CPacketBreak.Action.RELEASE_USE_ITEM, BlockPos.ORIGIN, Facing.DOWN));
|
||||
playerIn.stopUsingItem();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// /**
|
||||
// * Checks if the player is not creative, used for checking if it should break a block instantly
|
||||
// */
|
||||
// public boolean isNotCreative()
|
||||
// {
|
||||
// return !this.creative;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * returns true if player is in creative mode
|
||||
// */
|
||||
// public boolean isCreative()
|
||||
// {
|
||||
// return this.creative;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Checks if the player is riding a horse, used to chose the GUI to open
|
||||
// */
|
||||
// public boolean isRidingHorse()
|
||||
// {
|
||||
// return ;
|
||||
// }
|
||||
|
||||
// public Gamemode getGamemode()
|
||||
// {
|
||||
// return this.gamemode;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return isHittingBlock
|
||||
*/
|
||||
public boolean getIsHittingBlock()
|
||||
{
|
||||
return this.isHittingBlock;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue