diff --git a/pom.xml b/pom.xml
index 3119032..be90d37 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
Limbo
Limbo
- 0.2.1-ALPHA
+ 0.2.2-ALPHA
src
diff --git a/src/com/loohp/limbo/Limbo.java b/src/com/loohp/limbo/Limbo.java
index 1623e5a..1aace45 100644
--- a/src/com/loohp/limbo/Limbo.java
+++ b/src/com/loohp/limbo/Limbo.java
@@ -42,6 +42,7 @@ import com.loohp.limbo.Utils.ImageUtils;
import com.loohp.limbo.Utils.NetworkUtils;
import com.loohp.limbo.World.Schematic;
import com.loohp.limbo.World.World;
+import com.loohp.limbo.World.World.Environment;
import net.querz.nbt.io.NBTUtil;
import net.querz.nbt.tag.CompoundTag;
@@ -285,7 +286,7 @@ public class Limbo {
return null;
}
- World world = Schematic.toWorld(properties.getLevelName().getKey(), (CompoundTag) NBTUtil.read(schem).getTag());
+ World world = Schematic.toWorld(properties.getLevelName().getKey(), Environment.fromNamespacedKey(properties.getLevelDimension()), (CompoundTag) NBTUtil.read(schem).getTag());
console.sendMessage("Loaded world " + properties.getLevelName() + "!");
diff --git a/src/com/loohp/limbo/Player/Player.java b/src/com/loohp/limbo/Player/Player.java
index 920fc4b..e3b7050 100644
--- a/src/com/loohp/limbo/Player/Player.java
+++ b/src/com/loohp/limbo/Player/Player.java
@@ -9,7 +9,10 @@ import com.loohp.limbo.Events.PlayerChatEvent;
import com.loohp.limbo.Location.Location;
import com.loohp.limbo.Server.ClientConnection;
import com.loohp.limbo.Server.Packets.PacketPlayOutChat;
+import com.loohp.limbo.Server.Packets.PacketPlayOutGameState;
import com.loohp.limbo.Server.Packets.PacketPlayOutPositionAndLook;
+import com.loohp.limbo.Server.Packets.PacketPlayOutRespawn;
+import com.loohp.limbo.Utils.GameMode;
import com.loohp.limbo.World.World;
import net.md_5.bungee.api.chat.BaseComponent;
@@ -22,6 +25,7 @@ public class Player implements CommandSender {
private final String username;
private final UUID uuid;
+ private GameMode gamemode;
private int entityId;
@@ -35,10 +39,32 @@ public class Player implements CommandSender {
this.location = location.clone();
}
+ public GameMode getGamemode() {
+ return gamemode;
+ }
+
+ public void setGamemode(GameMode gamemode) {
+ if (!this.gamemode.equals(gamemode)) {
+ try {
+ PacketPlayOutGameState state = new PacketPlayOutGameState(3, gamemode.getId());
+ clientConnection.sendPacket(state);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ this.gamemode = gamemode;
+ }
+
+ @Deprecated
+ public void setGamemodeSilent(GameMode gamemode) {
+ this.gamemode = gamemode;
+ }
+
public World getWorld() {
return location.clone().getWorld();
}
+ @Deprecated
public void setEntityId(int entityId) {
this.entityId = entityId;
}
@@ -77,8 +103,11 @@ public class Player implements CommandSender {
public void teleport(Location location) {
try {
- PacketPlayOutPositionAndLook positionLook = new PacketPlayOutPositionAndLook(location.getX(),
- location.getY(), location.getZ(), location.getYaw(), location.getPitch(), 1);
+ if (!this.location.getWorld().equals(location.getWorld())) {
+ PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(location.getWorld(), 0, gamemode, false, false, true);
+ clientConnection.sendPacket(respawn);
+ }
+ PacketPlayOutPositionAndLook positionLook = new PacketPlayOutPositionAndLook(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch(), 1);
clientConnection.sendPacket(positionLook);
} catch (IOException e) {
e.printStackTrace();
diff --git a/src/com/loohp/limbo/Server/ClientConnection.java b/src/com/loohp/limbo/Server/ClientConnection.java
index f5243cc..aef5c0b 100644
--- a/src/com/loohp/limbo/Server/ClientConnection.java
+++ b/src/com/loohp/limbo/Server/ClientConnection.java
@@ -57,6 +57,7 @@ import com.loohp.limbo.Utils.CustomStringUtils;
import com.loohp.limbo.Utils.DataTypeIO;
import com.loohp.limbo.Utils.MojangAPIUtils;
import com.loohp.limbo.Utils.MojangAPIUtils.SkinResponse;
+import com.loohp.limbo.Utils.NamespacedKey;
import com.loohp.limbo.World.BlockPosition;
import com.loohp.limbo.World.DimensionRegistry;
import com.loohp.limbo.World.World;
@@ -154,6 +155,7 @@ public class ClientConnection extends Thread {
} catch (IOException e) {}
}
+ @SuppressWarnings("deprecation")
@Override
public void run() {
running = true;
@@ -258,8 +260,9 @@ public class ClientConnection extends Thread {
TimeUnit.MILLISECONDS.sleep(500);
ServerProperties p = Limbo.getInstance().getServerProperties();
- PacketPlayOutLogin join = new PacketPlayOutLogin(player.getEntityId(), false, p.getDefaultGamemode(), new String[] {p.getLevelName().toString()}, DimensionRegistry.getCodec(), p.getLevelDimension().toString(), p.getLevelName().toString(), 0, (byte) p.getMaxPlayers(), 8, p.isReducedDebugInfo(), true, false, false);
+ PacketPlayOutLogin join = new PacketPlayOutLogin(player.getEntityId(), false, p.getDefaultGamemode(), Limbo.getInstance().getWorlds().stream().map(each -> new NamespacedKey(each.getName()).toString()).collect(Collectors.toList()).toArray(new String[Limbo.getInstance().getWorlds().size()]), DimensionRegistry.getCodec(), p.getWorldSpawn().getWorld(), 0, (byte) p.getMaxPlayers(), 8, p.isReducedDebugInfo(), true, false, false);
sendPacket(join);
+ player.setGamemodeSilent(p.getDefaultGamemode());
Location s = p.getWorldSpawn();
diff --git a/src/com/loohp/limbo/Server/Packets/PacketPlayOutGameState.java b/src/com/loohp/limbo/Server/Packets/PacketPlayOutGameState.java
new file mode 100644
index 0000000..9bf839d
--- /dev/null
+++ b/src/com/loohp/limbo/Server/Packets/PacketPlayOutGameState.java
@@ -0,0 +1,37 @@
+package com.loohp.limbo.Server.Packets;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class PacketPlayOutGameState extends PacketOut {
+
+ private int reason;
+ private float value;
+
+ public PacketPlayOutGameState(int reason, float value) {
+ this.reason = reason;
+ this.value = value;
+ }
+
+ public int getReason() {
+ return reason;
+ }
+
+ public float getValue() {
+ return value;
+ }
+
+ @Override
+ public byte[] serializePacket() throws IOException {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ DataOutputStream output = new DataOutputStream(buffer);
+ output.writeByte(Packet.getPlayOut().get(getClass()));
+ output.writeByte(reason);
+ output.writeFloat(value);
+
+ return buffer.toByteArray();
+ }
+
+}
diff --git a/src/com/loohp/limbo/Server/Packets/PacketPlayOutLogin.java b/src/com/loohp/limbo/Server/Packets/PacketPlayOutLogin.java
index 5c29aa4..1263645 100644
--- a/src/com/loohp/limbo/Server/Packets/PacketPlayOutLogin.java
+++ b/src/com/loohp/limbo/Server/Packets/PacketPlayOutLogin.java
@@ -7,6 +7,8 @@ import java.nio.charset.StandardCharsets;
import com.loohp.limbo.Utils.DataTypeIO;
import com.loohp.limbo.Utils.GameMode;
+import com.loohp.limbo.Utils.NamespacedKey;
+import com.loohp.limbo.World.World;
import net.querz.nbt.tag.CompoundTag;
@@ -28,7 +30,7 @@ public class PacketPlayOutLogin extends PacketOut {
private boolean isFlat;
public PacketPlayOutLogin(int entityId, boolean isHardcore, GameMode gamemode,
- String[] worldsNames, CompoundTag dimensionCodec, String dimension, String worldName, long hashedSeed,
+ String[] worldsNames, CompoundTag dimensionCodec, World world, long hashedSeed,
byte maxPlayers, int viewDistance, boolean reducedDebugInfo, boolean enableRespawnScreen, boolean isDebug,
boolean isFlat) {
this.entityId = entityId;
@@ -36,8 +38,8 @@ public class PacketPlayOutLogin extends PacketOut {
this.gamemode = gamemode;
this.worldsNames = worldsNames;
this.dimensionCodec = dimensionCodec;
- this.dimension = dimension;
- this.worldName = worldName;
+ this.dimension = world.getEnvironment().getNamespacedKey().toString();
+ this.worldName = new NamespacedKey(world.getName()).toString();
this.hashedSeed = hashedSeed;
this.maxPlayers = maxPlayers;
this.viewDistance = viewDistance;
diff --git a/src/com/loohp/limbo/Server/Packets/PacketPlayOutRespawn.java b/src/com/loohp/limbo/Server/Packets/PacketPlayOutRespawn.java
new file mode 100644
index 0000000..e2d8101
--- /dev/null
+++ b/src/com/loohp/limbo/Server/Packets/PacketPlayOutRespawn.java
@@ -0,0 +1,80 @@
+package com.loohp.limbo.Server.Packets;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import com.loohp.limbo.Utils.DataTypeIO;
+import com.loohp.limbo.Utils.GameMode;
+import com.loohp.limbo.Utils.NamespacedKey;
+import com.loohp.limbo.World.World;
+
+public class PacketPlayOutRespawn extends PacketOut {
+
+ private String dimension;
+ private String worldName;
+ private long hashedSeed;
+ private GameMode gamemode;
+ private boolean isDebug;
+ private boolean isFlat;
+ private boolean copyMetaData;
+
+ public PacketPlayOutRespawn(World world, long hashedSeed, GameMode gamemode, boolean isDebug,
+ boolean isFlat, boolean copyMetaData) {
+ this.dimension = world.getEnvironment().getNamespacedKey().toString();
+ this.worldName = new NamespacedKey(world.getName()).toString();
+ this.hashedSeed = hashedSeed;
+ this.gamemode = gamemode;
+ this.isDebug = isDebug;
+ this.isFlat = isFlat;
+ this.copyMetaData = copyMetaData;
+ }
+
+ public String getDimension() {
+ return dimension;
+ }
+
+ public String getWorldName() {
+ return worldName;
+ }
+
+ public long getHashedSeed() {
+ return hashedSeed;
+ }
+
+ public GameMode getGamemode() {
+ return gamemode;
+ }
+
+ public boolean isDebug() {
+ return isDebug;
+ }
+
+ public boolean isFlat() {
+ return isFlat;
+ }
+
+ public boolean isCopyMetaData() {
+ return copyMetaData;
+ }
+
+ @Override
+ public byte[] serializePacket() throws IOException {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ DataOutputStream output = new DataOutputStream(buffer);
+ output.writeByte(Packet.getPlayOut().get(getClass()));
+ DataTypeIO.writeString(output, dimension, StandardCharsets.UTF_8);
+ DataTypeIO.writeString(output, worldName, StandardCharsets.UTF_8);
+ output.writeLong(hashedSeed);
+ output.writeByte((byte) gamemode.getId());
+ output.writeByte((byte) gamemode.getId());
+ output.writeBoolean(isDebug);
+ output.writeBoolean(isFlat);
+ output.writeBoolean(copyMetaData);
+
+ return buffer.toByteArray();
+ }
+
+}
diff --git a/src/com/loohp/limbo/World/Schematic.java b/src/com/loohp/limbo/World/Schematic.java
index 695db2a..1d5cbb1 100644
--- a/src/com/loohp/limbo/World/Schematic.java
+++ b/src/com/loohp/limbo/World/Schematic.java
@@ -5,6 +5,7 @@ import java.util.Iterator;
import java.util.Map;
import com.loohp.limbo.Utils.SchematicConvertionUtils;
+import com.loohp.limbo.World.World.Environment;
import net.querz.mca.Chunk;
import net.querz.nbt.tag.CompoundTag;
@@ -13,7 +14,7 @@ import net.querz.nbt.tag.ListTag;
public class Schematic {
- public static World toWorld(String name, CompoundTag nbt) {
+ public static World toWorld(String name, Environment environment, CompoundTag nbt) {
short width = nbt.getShort("Width");
short length = nbt.getShort("Length");
short height = nbt.getShort("Height");
@@ -25,7 +26,7 @@ public class Schematic {
mapping.put(palette.getInt(key), key);
}
- World world = new World(name, width, length);
+ World world = new World(name, width, length, environment);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
diff --git a/src/com/loohp/limbo/World/World.java b/src/com/loohp/limbo/World/World.java
index 9177bc7..07cd009 100644
--- a/src/com/loohp/limbo/World/World.java
+++ b/src/com/loohp/limbo/World/World.java
@@ -1,5 +1,6 @@
package com.loohp.limbo.World;
+import com.loohp.limbo.Utils.NamespacedKey;
import com.loohp.limbo.Utils.SchematicConvertionUtils;
import net.querz.mca.Chunk;
@@ -9,19 +10,31 @@ import net.querz.nbt.tag.ListTag;
public class World {
private String name;
+ private Environment environment;
private Chunk[][] chunks;
- public World(String name, int width, int length) {
+ public World(String name, int width, int length, Environment environment) {
this.name = name;
+ this.environment = environment;
this.chunks = new Chunk[(width >> 4) + 1][(length >> 4) + 1];
-
+
for (int x = 0; x < chunks.length; x++) {
for (int z = 0; z < chunks[x].length; z++) {
chunks[x][z] = Chunk.newChunk();
Chunk chunk = chunks[x][z];
chunk.cleanupPalettesAndBlockStates();
CompoundTag heightMap = new CompoundTag();
- heightMap.putLongArray("MOTION_BLOCKING", new long[] {1371773531765642314L,1389823183635651148L,1371738278539598925L,1389823183635388492L,1353688558756731469L,1389823114781694027L,1317765589597723213L,1371773531899860042L,1389823183635651149L,1371773462911685197L,1389823183635650636L,1353688626805119565L,1371773531900123211L,1335639250618849869L,1371738278674077258L,1389823114781694028L,1353723811310638154L,1371738278674077259L,1335674228429068364L,1335674228429067338L,1335674228698027594L,1317624576693539402L,1335709481520370249L,1299610178184057417L,1335638906349064264L,1299574993811968586L,1299574924958011464L,1299610178184056904L,1299574924958011464L,1299610109330100296L,1299574924958011464L,1299574924823793736L,1299574924958011465L,1281525273222484040L,1299574924958011464L,1281525273222484040L,9548107335L});
+ heightMap.putLongArray("MOTION_BLOCKING",
+ new long[] { 1371773531765642314L, 1389823183635651148L, 1371738278539598925L,
+ 1389823183635388492L, 1353688558756731469L, 1389823114781694027L, 1317765589597723213L,
+ 1371773531899860042L, 1389823183635651149L, 1371773462911685197L, 1389823183635650636L,
+ 1353688626805119565L, 1371773531900123211L, 1335639250618849869L, 1371738278674077258L,
+ 1389823114781694028L, 1353723811310638154L, 1371738278674077259L, 1335674228429068364L,
+ 1335674228429067338L, 1335674228698027594L, 1317624576693539402L, 1335709481520370249L,
+ 1299610178184057417L, 1335638906349064264L, 1299574993811968586L, 1299574924958011464L,
+ 1299610178184056904L, 1299574924958011464L, 1299610109330100296L, 1299574924958011464L,
+ 1299574924823793736L, 1299574924958011465L, 1281525273222484040L, 1299574924958011464L,
+ 1281525273222484040L, 9548107335L });
chunk.setHeightMaps(heightMap);
chunk.setBiomes(new int[256]);
chunk.setTileEntities(new ListTag(CompoundTag.class));
@@ -50,4 +63,33 @@ public class World {
public String getName() {
return name;
}
+
+ public Environment getEnvironment() {
+ return environment;
+ }
+
+ public enum Environment {
+ NORMAL(new NamespacedKey("minecraft:overworld")),
+ NETHER(new NamespacedKey("minecraft:the_nether")),
+ END(new NamespacedKey("minecraft:the_end"));
+
+ NamespacedKey key;
+
+ Environment(NamespacedKey key) {
+ this.key = key;
+ }
+
+ public NamespacedKey getNamespacedKey() {
+ return key;
+ }
+
+ public static Environment fromNamespacedKey(NamespacedKey key) {
+ for (Environment each : Environment.values()) {
+ if (each.getNamespacedKey().equals(key)) {
+ return each;
+ }
+ }
+ return null;
+ }
+ }
}
diff --git a/src/mapping.json b/src/mapping.json
index 806e36e..80eb8f6 100644
--- a/src/mapping.json
+++ b/src/mapping.json
@@ -34,7 +34,9 @@
"PacketPlayOutDisconnect": "0x1A",
"PacketPlayOutPluginMessaging": "0x17",
"PacketPlayOutTabComplete": "0x10",
- "PacketPlayOutDeclareCommands": "0x11"
+ "PacketPlayOutDeclareCommands": "0x11",
+ "PacketPlayOutRespawn": "0x3A",
+ "PacketPlayOutGameState": "0x1E"
},
"StatusIn": {
"0x01": "PacketStatusInPing",
diff --git a/src/permission.yml b/src/permission.yml
index 88d2981..662a2e5 100644
--- a/src/permission.yml
+++ b/src/permission.yml
@@ -3,6 +3,7 @@ groups:
- limboserver.stop
- limboserver.kick
- limboserver.say
+ - limboserver.gamemode
default:
- limboserver.spawn