mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-23 00:21:26 +01:00
Initial commit
This commit is contained in:
commit
9380770492
18
build.gradle
Normal file
18
build.gradle
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
}
|
||||||
|
|
||||||
|
group 'fr.themode.minestom'
|
||||||
|
version '1.0'
|
||||||
|
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||||
|
implementation 'com.github.Adamaq01:ozao-net:2.3.1'
|
||||||
|
}
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#Thu Aug 01 13:49:10 CEST 2019
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
|
172
gradlew
vendored
Normal file
172
gradlew
vendored
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
84
gradlew.bat
vendored
Normal file
84
gradlew.bat
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
2
settings.gradle
Normal file
2
settings.gradle
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
rootProject.name = 'Minestom'
|
||||||
|
|
61
src/main/java/fr/themode/minestom/Main.java
Normal file
61
src/main/java/fr/themode/minestom/Main.java
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package fr.themode.minestom;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.packet.Packet;
|
||||||
|
import fr.adamaq01.ozao.net.server.Connection;
|
||||||
|
import fr.adamaq01.ozao.net.server.Server;
|
||||||
|
import fr.adamaq01.ozao.net.server.ServerHandler;
|
||||||
|
import fr.adamaq01.ozao.net.server.backend.tcp.TCPServer;
|
||||||
|
import fr.themode.minestom.net.ConnectionManager;
|
||||||
|
import fr.themode.minestom.net.PacketProcessor;
|
||||||
|
import fr.themode.minestom.net.protocol.MinecraftProtocol;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
private static ConnectionManager connectionManager;
|
||||||
|
private static PacketProcessor packetProcessor;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
connectionManager = new ConnectionManager();
|
||||||
|
packetProcessor = new PacketProcessor(connectionManager);
|
||||||
|
|
||||||
|
Server server = new TCPServer(new MinecraftProtocol()).addHandler(new ServerHandler() {
|
||||||
|
@Override
|
||||||
|
public void onConnect(Server server, Connection connection) {
|
||||||
|
System.out.println("A connection");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisconnect(Server server, Connection connection) {
|
||||||
|
System.out.println("A DISCONNECTION");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPacketReceive(Server server, Connection connection, Packet packet) {
|
||||||
|
try {
|
||||||
|
packetProcessor.process(connection, packet);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onException(Server server, Connection connection, Throwable cause) {
|
||||||
|
cause.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.bind(25565);
|
||||||
|
System.out.println("Server started");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
src/main/java/fr/themode/minestom/entity/GameMode.java
Normal file
25
src/main/java/fr/themode/minestom/entity/GameMode.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
|
public enum GameMode {
|
||||||
|
|
||||||
|
SURVIVAL((byte) 0), CREATIVE((byte) 1), ADVENTURE((byte) 2), SPECTATOR((byte) 3);
|
||||||
|
|
||||||
|
private byte id;
|
||||||
|
private boolean hardcore;
|
||||||
|
|
||||||
|
GameMode(byte id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHardcore(boolean hardcore) {
|
||||||
|
this.hardcore = hardcore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHardcore() {
|
||||||
|
return hardcore;
|
||||||
|
}
|
||||||
|
}
|
12
src/main/java/fr/themode/minestom/entity/Player.java
Normal file
12
src/main/java/fr/themode/minestom/entity/Player.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
|
public class Player {
|
||||||
|
|
||||||
|
private PlayerConnection playerConnection;
|
||||||
|
|
||||||
|
public PlayerConnection getPlayerConnection() {
|
||||||
|
return playerConnection;
|
||||||
|
}
|
||||||
|
}
|
24
src/main/java/fr/themode/minestom/net/ConnectionManager.java
Normal file
24
src/main/java/fr/themode/minestom/net/ConnectionManager.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package fr.themode.minestom.net;
|
||||||
|
|
||||||
|
import fr.themode.minestom.entity.Player;
|
||||||
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class ConnectionManager {
|
||||||
|
|
||||||
|
private Set<PlayerConnection> connections = new HashSet<>();
|
||||||
|
private Map<PlayerConnection, Player> connectionPlayerMap = new HashMap<>();
|
||||||
|
|
||||||
|
public Player getPlayer(PlayerConnection connection) {
|
||||||
|
return connectionPlayerMap.get(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is only used at LoginStartPacket#process
|
||||||
|
public void createPlayer(PlayerConnection connection) {
|
||||||
|
this.connectionPlayerMap.put(connection, new Player());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package fr.themode.minestom.net;
|
||||||
|
|
||||||
|
public enum ConnectionState {
|
||||||
|
|
||||||
|
UNKNOWN, STATUS, LOGIN, PLAY;
|
||||||
|
|
||||||
|
}
|
80
src/main/java/fr/themode/minestom/net/PacketProcessor.java
Normal file
80
src/main/java/fr/themode/minestom/net/PacketProcessor.java
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package fr.themode.minestom.net;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.adamaq01.ozao.net.packet.Packet;
|
||||||
|
import fr.adamaq01.ozao.net.server.Connection;
|
||||||
|
import fr.themode.minestom.entity.Player;
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPreplayPacket;
|
||||||
|
import fr.themode.minestom.net.packet.client.handler.ClientLoginPacketsHandler;
|
||||||
|
import fr.themode.minestom.net.packet.client.handler.ClientPlayPacketsHandler;
|
||||||
|
import fr.themode.minestom.net.packet.client.handler.ClientStatusPacketsHandler;
|
||||||
|
import fr.themode.minestom.net.packet.client.handshake.HandshakePacket;
|
||||||
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static fr.themode.minestom.net.protocol.MinecraftProtocol.PACKET_ID_IDENTIFIER;
|
||||||
|
|
||||||
|
public class PacketProcessor {
|
||||||
|
|
||||||
|
private Map<Connection, PlayerConnection> connectionPlayerConnectionMap = new HashMap<>();
|
||||||
|
|
||||||
|
private ConnectionManager connectionManager;
|
||||||
|
|
||||||
|
// Protocols
|
||||||
|
private ClientStatusPacketsHandler statusPacketsHandler;
|
||||||
|
private ClientLoginPacketsHandler loginPacketsHandler;
|
||||||
|
private ClientPlayPacketsHandler playPacketsHandler;
|
||||||
|
|
||||||
|
public PacketProcessor(ConnectionManager connectionManager) {
|
||||||
|
this.connectionManager = connectionManager;
|
||||||
|
|
||||||
|
this.statusPacketsHandler = new ClientStatusPacketsHandler();
|
||||||
|
this.loginPacketsHandler = new ClientLoginPacketsHandler();
|
||||||
|
this.playPacketsHandler = new ClientPlayPacketsHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void process(Connection connection, Packet packet) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||||
|
int id = packet.get(PACKET_ID_IDENTIFIER);
|
||||||
|
System.out.println("RECEIVED ID: " + id);
|
||||||
|
Buffer buffer = packet.getPayload();
|
||||||
|
connectionPlayerConnectionMap.get(connection);
|
||||||
|
PlayerConnection playerConnection = connectionPlayerConnectionMap.computeIfAbsent(connection, c -> new PlayerConnection(c));
|
||||||
|
ConnectionState connectionState = playerConnection.getConnectionState();
|
||||||
|
|
||||||
|
if (connectionState == ConnectionState.UNKNOWN) {
|
||||||
|
// Should be handshake packet
|
||||||
|
if (id == 0) {
|
||||||
|
HandshakePacket handshakePacket = new HandshakePacket();
|
||||||
|
handshakePacket.read(buffer);
|
||||||
|
handshakePacket.process(playerConnection, connectionManager);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (connectionState) {
|
||||||
|
case PLAY:
|
||||||
|
Player player = connectionManager.getPlayer(playerConnection);
|
||||||
|
ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();
|
||||||
|
playPacket.read(buffer);
|
||||||
|
playPacket.process(player);
|
||||||
|
break;
|
||||||
|
case LOGIN:
|
||||||
|
ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();
|
||||||
|
loginPacket.read(buffer);
|
||||||
|
loginPacket.process(playerConnection, connectionManager);
|
||||||
|
break;
|
||||||
|
case STATUS:
|
||||||
|
ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();
|
||||||
|
statusPacket.read(buffer);
|
||||||
|
statusPacket.process(playerConnection, connectionManager);
|
||||||
|
break;
|
||||||
|
case UNKNOWN:
|
||||||
|
// Ignore packet (unexpected)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
|
||||||
|
public interface ClientPacket {
|
||||||
|
|
||||||
|
void read(Buffer buffer);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client;
|
||||||
|
|
||||||
|
import fr.themode.minestom.entity.Player;
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPacket;
|
||||||
|
|
||||||
|
public interface ClientPlayPacket extends ClientPacket {
|
||||||
|
|
||||||
|
void process(Player player);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client;
|
||||||
|
|
||||||
|
import fr.themode.minestom.net.ConnectionManager;
|
||||||
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
|
public interface ClientPreplayPacket extends ClientPacket {
|
||||||
|
|
||||||
|
void process(PlayerConnection connection, ConnectionManager connectionManager);
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.handler;
|
||||||
|
|
||||||
|
import fr.themode.minestom.net.packet.client.login.LoginStartPacket;
|
||||||
|
|
||||||
|
public class ClientLoginPacketsHandler extends ClientPacketsHandler {
|
||||||
|
|
||||||
|
public ClientLoginPacketsHandler() {
|
||||||
|
register(0, LoginStartPacket.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.handler;
|
||||||
|
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPacket;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ClientPacketsHandler {
|
||||||
|
|
||||||
|
private Map<Integer, Class<? extends ClientPacket>> idPacketMap = new HashMap<>();
|
||||||
|
|
||||||
|
public void register(int id, Class<? extends ClientPacket> packet) {
|
||||||
|
this.idPacketMap.put(id, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<? extends ClientPacket> getPacketClass(int id) {
|
||||||
|
return idPacketMap.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.handler;
|
||||||
|
|
||||||
|
import fr.themode.minestom.net.packet.client.play.ClientPluginMessagePacket;
|
||||||
|
import fr.themode.minestom.net.packet.client.play.ClientSettingsPacket;
|
||||||
|
|
||||||
|
public class ClientPlayPacketsHandler extends ClientPacketsHandler {
|
||||||
|
|
||||||
|
public ClientPlayPacketsHandler() {
|
||||||
|
register(0x05, ClientSettingsPacket.class);
|
||||||
|
register(0x0B, ClientPluginMessagePacket.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.handler;
|
||||||
|
|
||||||
|
import fr.themode.minestom.net.packet.client.status.PingPacket;
|
||||||
|
import fr.themode.minestom.net.packet.client.status.StatusRequestPacket;
|
||||||
|
|
||||||
|
public class ClientStatusPacketsHandler extends ClientPacketsHandler {
|
||||||
|
|
||||||
|
public ClientStatusPacketsHandler() {
|
||||||
|
register(0x00, StatusRequestPacket.class);
|
||||||
|
register(0x01, PingPacket.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.handshake;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.ConnectionManager;
|
||||||
|
import fr.themode.minestom.net.ConnectionState;
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPreplayPacket;
|
||||||
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
|
import static fr.themode.minestom.utils.Utils.readString;
|
||||||
|
import static fr.themode.minestom.utils.Utils.readVarInt;
|
||||||
|
|
||||||
|
public class HandshakePacket implements ClientPreplayPacket {
|
||||||
|
|
||||||
|
private int nextState;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Buffer buffer) {
|
||||||
|
int protocolVersion = readVarInt(buffer);
|
||||||
|
String serverAddress = readString(buffer);
|
||||||
|
short serverPort = buffer.getShort();
|
||||||
|
this.nextState = readVarInt(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(PlayerConnection connection, ConnectionManager connectionManager) {
|
||||||
|
switch (nextState) {
|
||||||
|
case 1:
|
||||||
|
connection.setConnectionState(ConnectionState.STATUS);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
connection.setConnectionState(ConnectionState.LOGIN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unexpected error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.login;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.entity.GameMode;
|
||||||
|
import fr.themode.minestom.net.ConnectionManager;
|
||||||
|
import fr.themode.minestom.net.ConnectionState;
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPreplayPacket;
|
||||||
|
import fr.themode.minestom.net.packet.server.login.JoinGamePacket;
|
||||||
|
import fr.themode.minestom.net.packet.server.login.LoginSuccessPacket;
|
||||||
|
import fr.themode.minestom.net.packet.server.play.SpawnPositionPacket;
|
||||||
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
import fr.themode.minestom.world.Dimension;
|
||||||
|
|
||||||
|
public class LoginStartPacket implements ClientPreplayPacket {
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(PlayerConnection connection, ConnectionManager connectionManager) {
|
||||||
|
// TODO send encryption request OR directly login success
|
||||||
|
LoginSuccessPacket successPacket = new LoginSuccessPacket(username);
|
||||||
|
connection.sendPacket(successPacket);
|
||||||
|
|
||||||
|
connection.setConnectionState(ConnectionState.PLAY);
|
||||||
|
connectionManager.createPlayer(connection);
|
||||||
|
|
||||||
|
// TODO complete login sequence with optionals packets
|
||||||
|
JoinGamePacket joinGamePacket = new JoinGamePacket();
|
||||||
|
joinGamePacket.entityId = 32;
|
||||||
|
joinGamePacket.gameMode = GameMode.SURVIVAL;
|
||||||
|
joinGamePacket.dimension = Dimension.OVERWORLD;
|
||||||
|
joinGamePacket.maxPlayers = 0;
|
||||||
|
joinGamePacket.levelType = "default";
|
||||||
|
joinGamePacket.reducedDebugInfo = false;
|
||||||
|
|
||||||
|
connection.sendPacket(joinGamePacket);
|
||||||
|
|
||||||
|
// TODO minecraft:brand plugin message
|
||||||
|
|
||||||
|
// TODO send server difficulty
|
||||||
|
|
||||||
|
// TODO player abilities
|
||||||
|
|
||||||
|
SpawnPositionPacket spawnPositionPacket = new SpawnPositionPacket();
|
||||||
|
spawnPositionPacket.x = 50;
|
||||||
|
spawnPositionPacket.y = 50;
|
||||||
|
spawnPositionPacket.z = 50;
|
||||||
|
|
||||||
|
// connection.sendPacket(spawnPositionPacket);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Buffer buffer) {
|
||||||
|
this.username = Utils.readString(buffer);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.entity.Player;
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
public class ClientPluginMessagePacket implements ClientPlayPacket {
|
||||||
|
|
||||||
|
private String identifier;
|
||||||
|
private byte[] data;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(Player player) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Buffer buffer) {
|
||||||
|
this.identifier = Utils.readString(buffer);
|
||||||
|
this.data = buffer.getAllBytes();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.entity.Player;
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
public class ClientSettingsPacket implements ClientPlayPacket {
|
||||||
|
|
||||||
|
private String locale;
|
||||||
|
private byte viewDistance;
|
||||||
|
// TODO chat mode
|
||||||
|
private boolean chatColors;
|
||||||
|
private byte displayedSkinParts;
|
||||||
|
// TODO main hand
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(Player player) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Buffer buffer) {
|
||||||
|
this.locale = Utils.readString(buffer);
|
||||||
|
this.viewDistance = buffer.getByte();
|
||||||
|
Utils.readVarInt(buffer); // chat mode
|
||||||
|
this.chatColors = buffer.getBoolean();
|
||||||
|
this.displayedSkinParts = buffer.getByte();
|
||||||
|
Utils.readVarInt(buffer); // main hand
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.entity.Player;
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||||
|
|
||||||
|
public class TestPacket implements ClientPlayPacket {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(Player player) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Buffer buffer) {
|
||||||
|
System.out.println("Hey c'est moi");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.status;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.ConnectionManager;
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPreplayPacket;
|
||||||
|
import fr.themode.minestom.net.packet.server.status.PongPacket;
|
||||||
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
|
public class PingPacket implements ClientPreplayPacket {
|
||||||
|
|
||||||
|
private long number;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(PlayerConnection connection, ConnectionManager connectionManager) {
|
||||||
|
PongPacket pongPacket = new PongPacket(number);
|
||||||
|
connection.sendPacket(pongPacket);
|
||||||
|
connection.getConnection().close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Buffer buffer) {
|
||||||
|
this.number = buffer.getLong();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package fr.themode.minestom.net.packet.client.status;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.ConnectionManager;
|
||||||
|
import fr.themode.minestom.net.packet.client.ClientPreplayPacket;
|
||||||
|
import fr.themode.minestom.net.packet.server.handshake.ResponsePacket;
|
||||||
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
|
public class StatusRequestPacket implements ClientPreplayPacket {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(PlayerConnection connection, ConnectionManager connectionManager) {
|
||||||
|
ResponsePacket responsePacket = new ResponsePacket();
|
||||||
|
connection.sendPacket(responsePacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Buffer buffer) {
|
||||||
|
// Empty
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
|
||||||
|
public interface ServerPacket {
|
||||||
|
|
||||||
|
void write(Buffer buffer);
|
||||||
|
|
||||||
|
int getId();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.handshake;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
public class ResponsePacket implements ServerPacket {
|
||||||
|
|
||||||
|
private static final String JSON_EXAMPLE = "{\n" +
|
||||||
|
" \"version\": {\n" +
|
||||||
|
" \"name\": \"1.14.4\",\n" +
|
||||||
|
" \"protocol\": 498\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"players\": {\n" +
|
||||||
|
" \"max\": 100,\n" +
|
||||||
|
" \"online\": 1,\n" +
|
||||||
|
" \"sample\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"name\": \"TheMode\",\n" +
|
||||||
|
" \"id\": \"4566e69f-c907-48ee-8d71-d7ba5aa00d20\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" },\t\n" +
|
||||||
|
" \"description\": {\n" +
|
||||||
|
" \"text\": \"Wallah les cubes\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"favicon\": \"data:image/png;base64,<data>\"\n" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
Utils.writeString(buffer, JSON_EXAMPLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.login;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.entity.GameMode;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
import fr.themode.minestom.world.Dimension;
|
||||||
|
|
||||||
|
public class JoinGamePacket implements ServerPacket {
|
||||||
|
|
||||||
|
public int entityId;
|
||||||
|
public GameMode gameMode = GameMode.SURVIVAL;
|
||||||
|
public Dimension dimension = Dimension.OVERWORLD;
|
||||||
|
public byte maxPlayers = 0; // Unused
|
||||||
|
public String levelType = "default";
|
||||||
|
public boolean reducedDebugInfo = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
int gameModeId = gameMode.getId();
|
||||||
|
if (gameMode.isHardcore())
|
||||||
|
gameModeId |= 8;
|
||||||
|
|
||||||
|
buffer.putInt(entityId);
|
||||||
|
buffer.putByte((byte) gameModeId);
|
||||||
|
buffer.putInt(dimension.getId());
|
||||||
|
buffer.putByte(maxPlayers);
|
||||||
|
Utils.writeString(buffer, levelType);
|
||||||
|
Utils.writeVarInt(buffer, 8);
|
||||||
|
buffer.putBoolean(reducedDebugInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x25;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.login;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class LoginSuccessPacket implements ServerPacket {
|
||||||
|
|
||||||
|
public String username;
|
||||||
|
|
||||||
|
public LoginSuccessPacket(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
Utils.writeString(buffer, UUID.randomUUID().toString()); // TODO mojang auth
|
||||||
|
Utils.writeString(buffer, username);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x02;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
import fr.themode.minestom.utils.Utils;
|
||||||
|
|
||||||
|
public class SpawnPositionPacket implements ServerPacket {
|
||||||
|
|
||||||
|
public int x, y, z;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
Utils.writePosition(buffer, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x49;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.play;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
|
||||||
|
public class WindowItemsPacket implements ServerPacket {
|
||||||
|
|
||||||
|
public byte windowId;
|
||||||
|
public short count;
|
||||||
|
|
||||||
|
// TODO slot data (Array of Slot)
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
buffer.putByte(windowId);
|
||||||
|
buffer.putShort(count);
|
||||||
|
// TODO replace with actual array of slot
|
||||||
|
buffer.putBoolean(false); // Not present
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x15;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package fr.themode.minestom.net.packet.server.status;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
|
||||||
|
public class PongPacket implements ServerPacket {
|
||||||
|
|
||||||
|
public long number;
|
||||||
|
|
||||||
|
public PongPacket(long number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Buffer buffer) {
|
||||||
|
buffer.putLong(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return 0x01;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package fr.themode.minestom.net.player;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.adamaq01.ozao.net.packet.Packet;
|
||||||
|
import fr.adamaq01.ozao.net.server.Connection;
|
||||||
|
import fr.themode.minestom.net.ConnectionState;
|
||||||
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
|
|
||||||
|
import static fr.themode.minestom.net.protocol.MinecraftProtocol.PACKET_ID_IDENTIFIER;
|
||||||
|
|
||||||
|
public class PlayerConnection {
|
||||||
|
|
||||||
|
private Connection connection;
|
||||||
|
private ConnectionState connectionState;
|
||||||
|
|
||||||
|
public PlayerConnection(Connection connection) {
|
||||||
|
this.connection = connection;
|
||||||
|
this.connectionState = ConnectionState.UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendPacket(ServerPacket serverPacket) {
|
||||||
|
Packet packet = Packet.create();
|
||||||
|
Buffer buffer = packet.getPayload();
|
||||||
|
serverPacket.write(buffer);
|
||||||
|
packet.put(PACKET_ID_IDENTIFIER, serverPacket.getId());
|
||||||
|
|
||||||
|
this.connection.sendPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connection getConnection() {
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnectionState(ConnectionState connectionState) {
|
||||||
|
this.connectionState = connectionState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConnectionState getConnectionState() {
|
||||||
|
return connectionState;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package fr.themode.minestom.net.protocol;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.adamaq01.ozao.net.packet.Packet;
|
||||||
|
import fr.adamaq01.ozao.net.protocol.Protocol;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static fr.themode.minestom.utils.Utils.readVarInt;
|
||||||
|
import static fr.themode.minestom.utils.Utils.writeVarInt;
|
||||||
|
|
||||||
|
public class MinecraftProtocol extends Protocol {
|
||||||
|
|
||||||
|
public static final String PACKET_ID_IDENTIFIER = "id";
|
||||||
|
|
||||||
|
public MinecraftProtocol() {
|
||||||
|
super("minecraft");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify(Buffer buffer) {
|
||||||
|
int length = readVarInt(buffer);
|
||||||
|
int realLength = buffer.slice(buffer.readerIndex()).length();
|
||||||
|
int id = readVarInt(buffer);
|
||||||
|
buffer.readerIndex(0);
|
||||||
|
return length == realLength && id >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify(Packet packet) {
|
||||||
|
return packet.get("id") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Buffer> cut(Buffer buffer) {
|
||||||
|
ArrayList<Buffer> buffers = new ArrayList<>();
|
||||||
|
int read = 0;
|
||||||
|
while (read < buffer.length()) {
|
||||||
|
int lengthLength = buffer.readerIndex(read).readerIndex();
|
||||||
|
int length = readVarInt(buffer);
|
||||||
|
lengthLength = buffer.readerIndex() - lengthLength;
|
||||||
|
buffers.add(buffer.sliceCopy(read, length + lengthLength));
|
||||||
|
read += length + lengthLength;
|
||||||
|
}
|
||||||
|
return buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Packet decode(Buffer buffer) {
|
||||||
|
int length = readVarInt(buffer);
|
||||||
|
int id = readVarInt(buffer);
|
||||||
|
Buffer packetPayload = buffer.sliceCopy(buffer.readerIndex());
|
||||||
|
return Packet.create(packetPayload).put(PACKET_ID_IDENTIFIER, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Buffer encode(Packet packet) {
|
||||||
|
Buffer buffer = Buffer.create();
|
||||||
|
Buffer idAndPayload = Buffer.create();
|
||||||
|
writeVarInt(idAndPayload, packet.get(PACKET_ID_IDENTIFIER));
|
||||||
|
idAndPayload.putBuffer(packet.getPayload());
|
||||||
|
writeVarInt(buffer, idAndPayload.length());
|
||||||
|
buffer.putBuffer(idAndPayload);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
111
src/main/java/fr/themode/minestom/utils/Utils.java
Normal file
111
src/main/java/fr/themode/minestom/utils/Utils.java
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
package fr.themode.minestom.utils;
|
||||||
|
|
||||||
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
public class Utils {
|
||||||
|
|
||||||
|
public static void writeString(Buffer buffer, String value) {
|
||||||
|
byte[] bytes = new byte[0];
|
||||||
|
try {
|
||||||
|
bytes = value.getBytes("UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (bytes.length > 32767) {
|
||||||
|
System.out.println("String too big (was " + value.length() + " bytes encoded, max " + 32767 + ")");
|
||||||
|
} else {
|
||||||
|
writeVarInt(buffer, bytes.length);
|
||||||
|
buffer.putBytes(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readString(Buffer buffer) {
|
||||||
|
int length = readVarInt(buffer);
|
||||||
|
byte bytes[] = buffer.getBytes(length);
|
||||||
|
try {
|
||||||
|
return new String(bytes, "UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeVarInt(Buffer buffer, int value) {
|
||||||
|
do {
|
||||||
|
byte temp = (byte) (value & 0b01111111);
|
||||||
|
value >>>= 7;
|
||||||
|
if (value != 0) {
|
||||||
|
temp |= 0b10000000;
|
||||||
|
}
|
||||||
|
buffer.putByte(temp);
|
||||||
|
} while (value != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int readVarInt(Buffer buffer) {
|
||||||
|
int numRead = 0;
|
||||||
|
int result = 0;
|
||||||
|
byte read;
|
||||||
|
do {
|
||||||
|
read = buffer.getByte();
|
||||||
|
int value = (read & 0b01111111);
|
||||||
|
result |= (value << (7 * numRead));
|
||||||
|
|
||||||
|
numRead++;
|
||||||
|
if (numRead > 5) {
|
||||||
|
throw new RuntimeException("VarInt is too big");
|
||||||
|
}
|
||||||
|
} while ((read & 0b10000000) != 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ??
|
||||||
|
public static int lengthVarInt(int value) {
|
||||||
|
int i = 0;
|
||||||
|
do {
|
||||||
|
i++;
|
||||||
|
byte temp = (byte) (value & 0b01111111);
|
||||||
|
value >>>= 7;
|
||||||
|
if (value != 0) {
|
||||||
|
temp |= 0b10000000;
|
||||||
|
}
|
||||||
|
} while (value != 0);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeVarLong(Buffer buffer, long value) {
|
||||||
|
do {
|
||||||
|
byte temp = (byte) (value & 0b01111111);
|
||||||
|
value >>>= 7;
|
||||||
|
if (value != 0) {
|
||||||
|
temp |= 0b10000000;
|
||||||
|
}
|
||||||
|
buffer.putByte(temp);
|
||||||
|
} while (value != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long readVarLong(Buffer buffer) {
|
||||||
|
int numRead = 0;
|
||||||
|
long result = 0;
|
||||||
|
byte read;
|
||||||
|
do {
|
||||||
|
read = buffer.getByte();
|
||||||
|
int value = (read & 0b01111111);
|
||||||
|
result |= (value << (7 * numRead));
|
||||||
|
|
||||||
|
numRead++;
|
||||||
|
if (numRead > 10) {
|
||||||
|
throw new RuntimeException("VarLong is too big");
|
||||||
|
}
|
||||||
|
} while ((read & 0b10000000) != 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writePosition(Buffer buffer, int x, int y, int z) {
|
||||||
|
buffer.putLong(((x & 0x3FFFFFF) << 38) | ((y & 0xFFF) << 26) | (z & 0x3FFFFFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
src/main/java/fr/themode/minestom/world/Difficulty.java
Normal file
16
src/main/java/fr/themode/minestom/world/Difficulty.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package fr.themode.minestom.world;
|
||||||
|
|
||||||
|
public enum Difficulty {
|
||||||
|
|
||||||
|
PEACEFUL((byte) 0), EASY((byte) 1), NORMAL((byte) 2), HARD((byte) 3);
|
||||||
|
|
||||||
|
private byte id;
|
||||||
|
|
||||||
|
Difficulty(byte id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
16
src/main/java/fr/themode/minestom/world/Dimension.java
Normal file
16
src/main/java/fr/themode/minestom/world/Dimension.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package fr.themode.minestom.world;
|
||||||
|
|
||||||
|
public enum Dimension {
|
||||||
|
|
||||||
|
NETHER(-1), OVERWORLD(0), END(1);
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
Dimension(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user