1.16 support (network), dimension flattening update

This commit is contained in:
Bixilon 2020-07-29 22:08:59 +02:00
parent b66212a7b2
commit a05a9ea8ac
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
30 changed files with 466 additions and 115 deletions

View File

@ -1,39 +0,0 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.game.datatypes;
public enum Dimension {
NETHER(-1),
OVERWORLD(0),
END(1);
final int id;
Dimension(int id) {
this.id = id;
}
public static Dimension byId(int id) {
for (Dimension g : values()) {
if (g.getId() == id) {
return g;
}
}
return null;
}
public int getId() {
return id;
}
}

View File

@ -20,7 +20,8 @@ public enum LevelType {
AMPLIFIED("amplified"),
DEFAULT_1_1("default_1_1"),
CUSTOMIZED("customized"),
BUFFET("buffet");
BUFFET("buffet"),
UNKNOWN("unknown");
final String type;

View File

@ -166,15 +166,13 @@ public class TextComponent {
if (json.has("extra")) {
JsonArray arr = json.getAsJsonArray("extra");
for (int i = 0; i < arr.size(); i++) {
JsonObject object;
try {
object = arr.get(i).getAsJsonObject();
} catch (Exception e) {
// reset text
if (arr.get(i).isJsonPrimitive()) {
buffer.append(ChatAttributes.RESET);
buffer.append(" ");
buffer.append(arr.get(i).getAsString());
continue;
}
JsonObject object = arr.get(i).getAsJsonObject();
if (object.has("bold") && object.get("bold").getAsBoolean()) {
buffer.append(ChatAttributes.BOLD);
}
@ -196,9 +194,22 @@ public class TextComponent {
buffer.append(object.get("text").getAsString());
}
buffer.append(ChatAttributes.RESET);
return buffer.toString();
}
return "";
if (json.has("with")) {
JsonArray arr = json.getAsJsonArray("with");
for (int i = 0; i < arr.size(); i++) {
if (arr.get(i).isJsonPrimitive()) {
buffer.append(ChatAttributes.RESET);
buffer.append(" ");
buffer.append(arr.get(i).getAsString());
continue;
}
JsonObject object = arr.get(i).getAsJsonObject();
buffer.append(object.get("text").getAsString());
}
buffer.append(ChatAttributes.RESET);
}
return buffer.toString();
}
@Override

View File

@ -95,8 +95,8 @@ public abstract class Entity implements EntityInterface {
this.pitch = pitch;
}
public void setEquipment(InventorySlots.EntityInventory slot, Slot data) {
equipment.put(slot, data);
public void setEquipment(HashMap<InventorySlots.EntityInventory, Slot> slots) {
equipment.putAll(slots);
}
public Slot getEquipment(InventorySlots.EntityInventory slot) {

View File

@ -19,6 +19,7 @@ import de.bixilon.minosoft.game.datatypes.Mappings;
import de.bixilon.minosoft.game.datatypes.objectLoader.blockIds.BlockIds;
import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block;
import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks;
import de.bixilon.minosoft.game.datatypes.objectLoader.dimensions.Dimensions;
import de.bixilon.minosoft.game.datatypes.objectLoader.effects.MobEffects;
import de.bixilon.minosoft.game.datatypes.objectLoader.enchantments.Enchantments;
import de.bixilon.minosoft.game.datatypes.objectLoader.entities.Entities;
@ -60,6 +61,9 @@ public class ObjectLoader {
Motives.load(mod, modJSON.getAsJsonObject("motive").getAsJsonObject("entries"), version);
Particles.load(mod, modJSON.getAsJsonObject("particle_type").getAsJsonObject("entries"), version);
MobEffects.load(mod, modJSON.getAsJsonObject("mob_effect").getAsJsonObject("entries"), version);
if (modJSON.has("dimension_type")) {
Dimensions.load(mod, modJSON.getAsJsonObject("dimension_type").getAsJsonObject("entries"), version);
}
break;
case BLOCKS:
Blocks.load(mod, modJSON, version);

View File

@ -0,0 +1,60 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.game.datatypes.objectLoader.dimensions;
public class Dimension {
final String mod;
final String identifier;
final boolean hasSkyLight;
public Dimension(String mod, String identifier, boolean hasSkyLight) {
this.mod = mod;
this.identifier = identifier;
this.hasSkyLight = hasSkyLight;
}
public String getMod() {
return mod;
}
public String getIdentifier() {
return identifier;
}
public boolean hasSkyLight() {
return hasSkyLight;
}
@Override
public String toString() {
return String.format("%s:%s", getMod(), getIdentifier());
}
@Override
public int hashCode() {
return mod.hashCode() * identifier.hashCode();
}
@Override
public boolean equals(Object obj) {
if (super.equals(obj)) {
return true;
}
if (hashCode() != obj.hashCode()) {
return false;
}
Dimension their = (Dimension) obj;
return getIdentifier().equals(their.getIdentifier()) && getMod().equals(their.getMod()) && hasSkyLight() == their.hasSkyLight();
}
}

View File

@ -0,0 +1,66 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.game.datatypes.objectLoader.dimensions;
import com.google.common.collect.HashBiMap;
import com.google.gson.JsonObject;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
import java.util.HashMap;
public class Dimensions {
static HashMap<ProtocolVersion, HashBiMap<Integer, Dimension>> dimensionIdMap = new HashMap<>(); // version -> (protocolId > Dimension)
static HashBiMap<String, Dimension> dimensionIdentifierMap = HashBiMap.create(); // Identifier, Dimension
static HashMap<String, HashMap<String, Dimension>> customDimensionIdentifierMap = new HashMap<>(); // Mod -> (Identifier, Dimension): used > 1.16
public static Dimension byId(int protocolId, ProtocolVersion version) {
if (version.getVersionNumber() < ProtocolVersion.VERSION_1_12_2.getVersionNumber()) {
version = ProtocolVersion.VERSION_1_12_2;
}
return dimensionIdMap.get(version).get(protocolId);
}
public static Dimension byIdentifier(String identifier) {
String[] splitted = identifier.split(":", 2);
return byIdentifier(splitted[0], splitted[1]);
}
public static Dimension byIdentifier(String mod, String identifier) {
if (mod == "minecraft") {
return dimensionIdentifierMap.get(identifier);
}
if (customDimensionIdentifierMap.containsKey(mod)) {
return customDimensionIdentifierMap.get(mod).get(identifier);
}
return null;
}
public static void load(String mod, JsonObject json, ProtocolVersion version) {
HashBiMap<Integer, Dimension> versionIdMapping = HashBiMap.create();
for (String identifierName : json.keySet()) {
JsonObject identifierJSON = json.getAsJsonObject(identifierName);
Dimension dimension = new Dimension(mod, identifierName, identifierJSON.get("has_skylight").getAsBoolean());
if (identifierJSON.has("id")) {
versionIdMapping.put(identifierJSON.get("id").getAsInt(), dimension);
continue;
}
dimensionIdentifierMap.put(identifierName, dimension);
}
if (versionIdMapping.size() > 0) {
dimensionIdMap.put(version, versionIdMapping);
}
}
}

View File

@ -48,6 +48,12 @@ public class Recipe {
this.result = result;
}
public Recipe(RecipeTypes type, Ingredient base, Ingredient addition, Slot result) {
this.type = type;
this.ingredients = new Ingredient[]{base, addition};
this.result = result;
}
public Recipe(RecipeTypes type, String group, Ingredient ingredient, Slot result, float experience, int cookingTime) {
this.type = type;
this.group = group;

View File

@ -34,7 +34,8 @@ public enum RecipeTypes {
BLASTING("blasting"),
SMOKING("smoking"),
CAMPFIRE("campfire_cooking"),
STONE_CUTTING("stonecutting");
STONE_CUTTING("stonecutting"),
SMITHING("smithing");
final String name;

View File

@ -13,10 +13,10 @@
package de.bixilon.minosoft.game.datatypes.world;
import de.bixilon.minosoft.game.datatypes.Dimension;
import de.bixilon.minosoft.game.datatypes.entities.Entity;
import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block;
import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks;
import de.bixilon.minosoft.game.datatypes.objectLoader.dimensions.Dimension;
import de.bixilon.minosoft.nbt.tag.CompoundTag;
import java.util.HashMap;

View File

@ -157,8 +157,9 @@ public class Network {
}
InPacketBuffer inPacketBuffer = new InPacketBuffer(data, connection.getVersion());
Packets.Clientbound p = null;
try {
Packets.Clientbound p = connection.getVersion().getProtocol().getPacketByCommand(connection.getConnectionState(), inPacketBuffer.getCommand());
p = connection.getVersion().getProtocol().getPacketByCommand(connection.getConnectionState(), inPacketBuffer.getCommand());
Class<? extends ClientboundPacket> clazz = Protocol.getPacketByPacket(p);
if (clazz == null) {
@ -195,7 +196,7 @@ public class Network {
e.printStackTrace();
}
} catch (Exception e) {
Log.protocol(String.format("An error occurred while parsing an packet: %s", e));
Log.protocol(String.format("An error occurred while parsing an packet (%s): %s", p, e));
e.printStackTrace();
}
}

View File

@ -35,12 +35,12 @@ public class PacketBlockEntityMetadata implements ClientboundPacket {
case VERSION_1_7_10:
position = buffer.readBlockPositionShort();
action = Actions.byId(buffer.readByte(), buffer.getVersion());
nbt = buffer.readNBT(true);
nbt = (CompoundTag) buffer.readNBT(true);
return true;
default:
position = buffer.readPosition();
action = Actions.byId(buffer.readByte(), buffer.getVersion());
nbt = buffer.readNBT();
nbt = (CompoundTag) buffer.readNBT();
return true;
}
}

View File

@ -13,7 +13,7 @@
package de.bixilon.minosoft.protocol.packets.clientbound.play;
import de.bixilon.minosoft.game.datatypes.Dimension;
import de.bixilon.minosoft.game.datatypes.objectLoader.dimensions.Dimension;
import de.bixilon.minosoft.game.datatypes.world.BlockPosition;
import de.bixilon.minosoft.game.datatypes.world.Chunk;
import de.bixilon.minosoft.game.datatypes.world.ChunkLocation;
@ -43,7 +43,7 @@ public class PacketChunkData implements ClientboundPacket {
}
public boolean read(InPacketBuffer buffer, Dimension dimension) {
boolean containsSkyLight = dimension == Dimension.OVERWORLD;
boolean containsSkyLight = dimension.hasSkyLight();
if (buffer.getVersion().getVersionNumber() <= ProtocolVersion.VERSION_1_7_10.getVersionNumber()) {
this.location = new ChunkLocation(buffer.readInt(), buffer.readInt());
boolean groundUpContinuous = buffer.readBoolean();
@ -74,7 +74,7 @@ public class PacketChunkData implements ClientboundPacket {
}
short sectionBitMask = (short) buffer.readVarInt();
if (buffer.getVersion().getVersionNumber() >= ProtocolVersion.VERSION_1_14_4.getVersionNumber()) {
heightMap = buffer.readNBT();
heightMap = (CompoundTag) buffer.readNBT();
}
if (groundUpContinuous) {
if (buffer.getVersion().getVersionNumber() >= ProtocolVersion.VERSION_1_16_2.getVersionNumber()) {
@ -93,7 +93,7 @@ public class PacketChunkData implements ClientboundPacket {
}
int blockEntitiesCount = buffer.readVarInt();
for (int i = 0; i < blockEntitiesCount; i++) {
CompoundTag tag = buffer.readNBT();
CompoundTag tag = (CompoundTag) buffer.readNBT();
blockEntities.put(new BlockPosition(tag.getIntTag("x").getValue(), (short) tag.getIntTag("y").getValue(), tag.getIntTag("z").getValue()), tag);
}
return true;

View File

@ -79,6 +79,13 @@ public class PacketDeclareRecipes implements ClientboundPacket {
recipe = new Recipe(type, group, ingredient, result);
break;
}
case SMITHING: {
Ingredient base = buffer.readIngredient();
Ingredient addition = buffer.readIngredient();
Slot result = buffer.readSlot();
recipe = new Recipe(type, base, addition, result);
break;
}
default:
recipe = new Recipe(type);
break;

View File

@ -19,41 +19,53 @@ import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
import java.util.HashMap;
import java.util.Map;
public class PacketEntityEquipment implements ClientboundPacket {
int entityId;
InventorySlots.EntityInventory slot;
Slot data;
HashMap<InventorySlots.EntityInventory, Slot> slots = new HashMap<>();
@Override
public boolean read(InByteBuffer buffer) {
switch (buffer.getVersion()) {
case VERSION_1_7_10:
entityId = buffer.readInt();
this.slot = InventorySlots.EntityInventory.byId(buffer.readShort(), buffer.getVersion());
this.data = buffer.readSlot();
return true;
case VERSION_1_8:
entityId = buffer.readVarInt();
this.slot = InventorySlots.EntityInventory.byId(buffer.readShort(), buffer.getVersion());
this.data = buffer.readSlot();
return true;
default:
entityId = buffer.readVarInt();
this.slot = InventorySlots.EntityInventory.byId(buffer.readVarInt(), buffer.getVersion());
this.data = buffer.readSlot();
return true;
if (buffer.getVersion() == ProtocolVersion.VERSION_1_7_10) {
entityId = buffer.readInt();
slots.put(InventorySlots.EntityInventory.byId(buffer.readShort(), buffer.getVersion()), buffer.readSlot());
return true;
}
if (buffer.getVersion() == ProtocolVersion.VERSION_1_8) {
entityId = buffer.readVarInt();
slots.put(InventorySlots.EntityInventory.byId(buffer.readShort(), buffer.getVersion()), buffer.readSlot());
return true;
}
if (buffer.getVersion().getVersionNumber() < ProtocolVersion.VERSION_1_16_2.getVersionNumber()) {
entityId = buffer.readVarInt();
slots.put(InventorySlots.EntityInventory.byId(buffer.readVarInt(), buffer.getVersion()), buffer.readSlot());
return true;
}
entityId = buffer.readVarInt();
boolean slotAvailable = true;
while (slotAvailable) {
int slotId = buffer.readByte();
if (slotId >= 0) {
slotAvailable = false;
}
slotId &= 0x7F;
slots.put(InventorySlots.EntityInventory.byId(slotId, buffer.getVersion()), buffer.readSlot());
}
return true;
}
@Override
public void log() {
if (data != null) {
Log.protocol(String.format("Entity equipment changed (entityId=%d, slot=%s): %dx %s", entityId, slot, data.getItemCount(), data.getDisplayName()));
if (slots.size() == 1) {
Map.Entry<InventorySlots.EntityInventory, Slot> set = slots.entrySet().iterator().next();
Log.protocol(String.format("Entity equipment changed (entityId=%d, slot=%s): %dx %s", entityId, set.getKey(), set.getValue().getItemCount(), set.getValue().getDisplayName()));
} else {
// null means nothing, means air
Log.protocol(String.format("Entity equipment changed (entityId=%d, slot=%s): AIR", entityId, slot));
Log.protocol(String.format("Entity equipment changed (entityId=%d, slotCount=%d)", entityId, slots.size()));
}
}
@ -66,11 +78,7 @@ public class PacketEntityEquipment implements ClientboundPacket {
return entityId;
}
public InventorySlots.EntityInventory getSlot() {
return slot;
}
public Slot getData() {
return data;
public HashMap<InventorySlots.EntityInventory, Slot> getSlots() {
return slots;
}
}

View File

@ -14,16 +14,22 @@
package de.bixilon.minosoft.protocol.packets.clientbound.play;
import de.bixilon.minosoft.game.datatypes.Difficulty;
import de.bixilon.minosoft.game.datatypes.Dimension;
import de.bixilon.minosoft.game.datatypes.GameMode;
import de.bixilon.minosoft.game.datatypes.LevelType;
import de.bixilon.minosoft.game.datatypes.objectLoader.dimensions.Dimension;
import de.bixilon.minosoft.game.datatypes.objectLoader.dimensions.Dimensions;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.nbt.tag.CompoundTag;
import de.bixilon.minosoft.nbt.tag.ListTag;
import de.bixilon.minosoft.nbt.tag.NBTTag;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
import de.bixilon.minosoft.util.BitByte;
import java.util.HashMap;
public class PacketJoinGame implements ClientboundPacket {
int entityId;
boolean hardcore;
@ -35,7 +41,7 @@ public class PacketJoinGame implements ClientboundPacket {
LevelType levelType;
boolean reducedDebugScreen;
boolean enableRespawnScreen = true;
HashMap<String, HashMap<String, Dimension>> dimensions;
@Override
public boolean read(InByteBuffer buffer) {
@ -49,7 +55,7 @@ public class PacketJoinGame implements ClientboundPacket {
gameModeRaw &= ~0x8;
gameMode = GameMode.byId(gameModeRaw);
dimension = Dimension.byId(buffer.readByte());
dimension = Dimensions.byId(buffer.readInt(), buffer.getVersion());
difficulty = Difficulty.byId(buffer.readByte());
maxPlayers = buffer.readByte();
levelType = LevelType.byType(buffer.readString());
@ -72,7 +78,7 @@ public class PacketJoinGame implements ClientboundPacket {
gameModeRaw &= ~0x8;
gameMode = GameMode.byId(gameModeRaw);
dimension = Dimension.byId(buffer.readInt());
dimension = Dimensions.byId(buffer.readInt(), buffer.getVersion());
difficulty = Difficulty.byId(buffer.readByte());
maxPlayers = buffer.readByte();
levelType = LevelType.byType(buffer.readString());
@ -87,7 +93,7 @@ public class PacketJoinGame implements ClientboundPacket {
gameModeRaw &= ~0x8;
gameMode = GameMode.byId(gameModeRaw);
dimension = Dimension.byId(buffer.readInt());
dimension = Dimensions.byId(buffer.readInt(), buffer.getVersion());
maxPlayers = buffer.readByte();
levelType = LevelType.byType(buffer.readString());
viewDistance = buffer.readVarInt();
@ -102,7 +108,7 @@ public class PacketJoinGame implements ClientboundPacket {
gameModeRaw &= ~0x8;
gameMode = GameMode.byId(gameModeRaw);
dimension = Dimension.byId(buffer.readInt());
dimension = Dimensions.byId(buffer.readInt(), buffer.getVersion());
long hashedSeed = buffer.readLong();
maxPlayers = buffer.readByte();
levelType = LevelType.byType(buffer.readString());
@ -111,9 +117,31 @@ public class PacketJoinGame implements ClientboundPacket {
enableRespawnScreen = buffer.readBoolean();
return true;
}
default: {
this.entityId = buffer.readInt();
hardcore = buffer.readBoolean();
gameMode = GameMode.byId(buffer.readByte());
buffer.readByte(); // previous game mode
// worlds
String[] worlds = buffer.readStringArray(buffer.readVarInt());
NBTTag dimensionCodec = buffer.readNBT();
dimensions = parseDimensionCodec(dimensionCodec);
String[] currentDimensionSplit = buffer.readString().split(":", 2);
dimension = dimensions.get(currentDimensionSplit[0]).get(currentDimensionSplit[1]);
buffer.readString(); // world name
long hashedSeed = buffer.readLong();
maxPlayers = buffer.readByte();
levelType = LevelType.UNKNOWN;
viewDistance = buffer.readVarInt();
reducedDebugScreen = buffer.readBoolean();
enableRespawnScreen = buffer.readBoolean();
boolean isDebug = buffer.readBoolean();
if (buffer.readBoolean()) {
levelType = LevelType.FLAT;
}
return true;
}
}
return false;
}
@Override
@ -126,6 +154,21 @@ public class PacketJoinGame implements ClientboundPacket {
h.handle(this);
}
private HashMap<String, HashMap<String, Dimension>> parseDimensionCodec(NBTTag nbt) {
HashMap<String, HashMap<String, Dimension>> dimensionMap = new HashMap<>();
ListTag listTag = ((CompoundTag) nbt).getCompoundTag("minecraft:dimension_type").getListTag("value");
for (NBTTag tag : listTag.getValue()) {
CompoundTag compoundTag = (CompoundTag) tag;
String[] name = compoundTag.getStringTag("name").getValue().split(":", 2);
if (!dimensionMap.containsKey(name[0])) {
dimensionMap.put(name[0], new HashMap<>());
}
dimensionMap.get(name[0]).put(name[1], new Dimension(name[0], name[1], compoundTag.getByteTag("has_skylight").getValue() == 0x01));
}
return dimensionMap;
}
public boolean isHardcore() {
return hardcore;
}

View File

@ -27,7 +27,7 @@ public class PacketNBTQueryResponse implements ClientboundPacket {
@Override
public boolean read(InByteBuffer buffer) {
transactionId = buffer.readVarInt();
tag = buffer.readNBT();
tag = (CompoundTag) buffer.readNBT();
return true;
}

View File

@ -14,9 +14,10 @@
package de.bixilon.minosoft.protocol.packets.clientbound.play;
import de.bixilon.minosoft.game.datatypes.Difficulty;
import de.bixilon.minosoft.game.datatypes.Dimension;
import de.bixilon.minosoft.game.datatypes.GameMode;
import de.bixilon.minosoft.game.datatypes.LevelType;
import de.bixilon.minosoft.game.datatypes.objectLoader.dimensions.Dimension;
import de.bixilon.minosoft.game.datatypes.objectLoader.dimensions.Dimensions;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
@ -27,7 +28,10 @@ public class PacketRespawn implements ClientboundPacket {
Difficulty difficulty;
GameMode gameMode;
LevelType levelType;
long hashedSeed;
boolean isDebug = false;
boolean isFlat = false;
boolean copyMetaData = false;
@Override
public boolean read(InByteBuffer buffer) {
@ -39,21 +43,31 @@ public class PacketRespawn implements ClientboundPacket {
case VERSION_1_11_2:
case VERSION_1_12_2:
case VERSION_1_13_2:
dimension = Dimension.byId(buffer.readInt());
dimension = Dimensions.byId(buffer.readInt(), buffer.getVersion());
difficulty = Difficulty.byId(buffer.readByte());
gameMode = GameMode.byId(buffer.readByte());
levelType = LevelType.byType(buffer.readString());
return true;
case VERSION_1_14_4:
dimension = Dimension.byId(buffer.readInt());
dimension = Dimensions.byId(buffer.readInt(), buffer.getVersion());
gameMode = GameMode.byId(buffer.readByte());
levelType = LevelType.byType(buffer.readString());
return true;
case VERSION_1_15_2:
dimension = Dimensions.byId(buffer.readInt(), buffer.getVersion());
hashedSeed = buffer.readLong();
gameMode = GameMode.byId(buffer.readByte());
levelType = LevelType.byType(buffer.readString());
return true;
default:
dimension = Dimension.byId(buffer.readInt());
long hashedSeed = buffer.readLong();
dimension = Dimensions.byIdentifier(buffer.readString());
buffer.readString(); // world
hashedSeed = buffer.readLong();
gameMode = GameMode.byId(buffer.readByte());
levelType = LevelType.byType(buffer.readString());
buffer.readByte(); // previous game mode
isDebug = buffer.readBoolean();
isFlat = buffer.readBoolean();
copyMetaData = buffer.readBoolean();
return true;
}
}

View File

@ -19,13 +19,18 @@ import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ClientboundPacket;
import de.bixilon.minosoft.protocol.protocol.InByteBuffer;
import de.bixilon.minosoft.protocol.protocol.PacketHandler;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
public class PacketUnlockRecipes implements ClientboundPacket {
UnlockRecipeActions action;
boolean isCraftingBookOpen;
boolean isSmeltingBookOpen;
boolean isSmeltingBookOpen = false;
boolean isBlastFurnaceBookOpen = false;
boolean isSmokerBookOpen = false;
boolean isCraftingFilteringActive;
boolean isSmeltingFilteringActive;
boolean isSmeltingFilteringActive = false;
boolean isBlastFurnaceFilteringActive = false;
boolean isSmokerFilteringActive = false;
Recipe[] listed;
Recipe[] tagged;
@ -54,6 +59,12 @@ public class PacketUnlockRecipes implements ClientboundPacket {
isCraftingFilteringActive = buffer.readBoolean();
isSmeltingBookOpen = buffer.readBoolean();
isSmeltingFilteringActive = buffer.readBoolean();
if (buffer.getVersion().getVersionNumber() >= ProtocolVersion.VERSION_1_16_2.getVersionNumber()) {
isBlastFurnaceBookOpen = buffer.readBoolean();
isBlastFurnaceFilteringActive = buffer.readBoolean();
isSmokerBookOpen = buffer.readBoolean();
isSmokerFilteringActive = buffer.readBoolean();
}
listed = new Recipe[buffer.readVarInt()];
for (int i = 0; i < listed.length; i++) {
listed[i] = Recipes.getRecipe(buffer.readString());
@ -86,6 +97,30 @@ public class PacketUnlockRecipes implements ClientboundPacket {
return isCraftingFilteringActive;
}
public boolean isBlastFurnaceBookOpen() {
return isBlastFurnaceBookOpen;
}
public boolean isBlastFurnaceFilteringActive() {
return isBlastFurnaceFilteringActive;
}
public boolean isSmeltingBookOpen() {
return isSmeltingBookOpen;
}
public boolean isSmeltingFilteringActive() {
return isSmeltingFilteringActive;
}
public boolean isSmokerBookOpen() {
return isSmokerBookOpen;
}
public boolean isSmokerFilteringActive() {
return isSmokerFilteringActive;
}
public Recipe[] getListed() {
return listed;
}

View File

@ -0,0 +1,48 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.protocol.packets.serverbound.play;
import de.bixilon.minosoft.game.datatypes.world.BlockPosition;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ServerboundPacket;
import de.bixilon.minosoft.protocol.protocol.OutPacketBuffer;
import de.bixilon.minosoft.protocol.protocol.Packets;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
public class PacketGenerateStructure implements ServerboundPacket {
final BlockPosition position;
final int levels;
final boolean keepJigsaw;
public PacketGenerateStructure(BlockPosition position, int levels, boolean keepJigsaw) {
this.position = position;
this.levels = levels;
this.keepJigsaw = keepJigsaw;
}
@Override
public OutPacketBuffer write(ProtocolVersion version) {
OutPacketBuffer buffer = new OutPacketBuffer(version, version.getPacketCommand(Packets.Serverbound.PLAY_GENERATE_STRUCTURE));
buffer.writePosition(position);
buffer.writeVarInt(levels);
buffer.writeBoolean(keepJigsaw);
return buffer;
}
@Override
public void log() {
Log.protocol(String.format("Sending generate structure packet (position=%s, levels=%d, keepJigsaw=%s)", position, levels, keepJigsaw));
}
}

View File

@ -28,6 +28,7 @@ public class PacketInteractEntity implements ServerboundPacket {
final Location location;
final Hand hand;
boolean sneaking;
public PacketInteractEntity(Entity entity, Click click) {
this.entityId = entity.getEntityId();
@ -57,6 +58,14 @@ public class PacketInteractEntity implements ServerboundPacket {
this.hand = hand;
}
public PacketInteractEntity(int entityId, Click click, Location location, Hand hand, boolean sneaking) {
this.entityId = entityId;
this.click = click;
this.location = location;
this.hand = hand;
this.sneaking = sneaking;
}
@Override
public OutPacketBuffer write(ProtocolVersion version) {
@ -86,6 +95,9 @@ public class PacketInteractEntity implements ServerboundPacket {
buffer.writeFloat((float) location.getZ());
buffer.writeVarInt(hand.getId());
}
if (version.getVersionNumber() >= ProtocolVersion.VERSION_1_16_2.getVersionNumber()) {
buffer.writeBoolean(sneaking);
}
break;
}
return buffer;

View File

@ -30,14 +30,16 @@ public class PacketPlayerAbilitiesSending implements ServerboundPacket {
@Override
public OutPacketBuffer write(ProtocolVersion version) {
OutPacketBuffer buffer = new OutPacketBuffer(version, version.getPacketCommand(Packets.Serverbound.PLAY_PLAYER_ABILITIES));
// only fly matters, everything else ignored
byte flags = 0;
if (flying) {
flags |= 0b10;
}
buffer.writeByte(flags);
buffer.writeFloat(0.0F);
buffer.writeFloat(0.0F);
if (version.getVersionNumber() < ProtocolVersion.VERSION_1_16_2.getVersionNumber()) {
// only fly matters, everything else ignored
buffer.writeFloat(0.0F);
buffer.writeFloat(0.0F);
}
return buffer;
}

View File

@ -0,0 +1,41 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.protocol.packets.serverbound.play;
import de.bixilon.minosoft.game.datatypes.objectLoader.recipes.Recipe;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.protocol.packets.ServerboundPacket;
import de.bixilon.minosoft.protocol.protocol.OutPacketBuffer;
import de.bixilon.minosoft.protocol.protocol.Packets;
import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
public class PacketSetDisplayedRecipe implements ServerboundPacket {
final Recipe recipe;
public PacketSetDisplayedRecipe(Recipe recipe) {
this.recipe = recipe;
}
@Override
public OutPacketBuffer write(ProtocolVersion version) {
OutPacketBuffer buffer = new OutPacketBuffer(version, version.getPacketCommand(Packets.Serverbound.PLAY_SET_DISPLAYED_RECIPE));
buffer.writeString(recipe.getResult().getItem().getMod() + ":" + recipe.getResult().getItem().getIdentifier());
return buffer;
}
@Override
public void log() {
Log.protocol(String.format("Sending set displayed recipe packet (identifier=%s:%s)", recipe.getResult().getItem().getMod(), recipe.getResult().getItem().getIdentifier()));
}
}

View File

@ -22,9 +22,12 @@ import de.bixilon.minosoft.protocol.protocol.ProtocolVersion;
public class PacketUpdateJigsawBlock implements ServerboundPacket {
final BlockPosition position;
final String attachmentType;
String attachmentType;
final String targetPool;
final String finalState;
String name;
String target;
String jointType;
public PacketUpdateJigsawBlock(BlockPosition position, String attachmentType, String targetPool, String finalState) {
this.position = position;
@ -34,10 +37,31 @@ public class PacketUpdateJigsawBlock implements ServerboundPacket {
}
public PacketUpdateJigsawBlock(BlockPosition position, String name, String target, String targetPool, String finalState, String jointType) {
this.position = position;
this.name = name;
this.target = target;
this.targetPool = targetPool;
this.finalState = finalState;
this.jointType = jointType;
}
@Override
public OutPacketBuffer write(ProtocolVersion version) {
OutPacketBuffer buffer = new OutPacketBuffer(version, version.getPacketCommand(Packets.Serverbound.PLAY_UPDATE_JIGSAW_BLOCK));
buffer.writePosition(position);
if (version.getVersionNumber() < ProtocolVersion.VERSION_1_16_2.getVersionNumber()) {
buffer.writeString(attachmentType);
buffer.writeString(targetPool);
buffer.writeString(finalState);
return buffer;
}
buffer.writeString(name);
buffer.writeString(target);
buffer.writeString(targetPool);
buffer.writeString(finalState);
buffer.writeString(jointType);
return buffer;
}

View File

@ -286,7 +286,7 @@ public class InByteBuffer {
// shouldn't be a subtag
return new CompoundTag(false, this);
}
return readNBT();
return readNBT(type);
}
public NBTTag readNBT(TagTypes tagType) {

View File

@ -182,6 +182,10 @@ public class PacketHandler {
connection.getPlayer().setFood(pkg.getFood());
connection.getPlayer().setHealth(pkg.getHealth());
connection.getPlayer().setSaturation(pkg.getSaturation());
if (pkg.getHealth() <= 0.0F) {
// do respawn
connection.getSender().respawn();
}
}
public void handle(PacketPluginMessageReceiving pkg) {
@ -286,7 +290,7 @@ public class PacketHandler {
}
public void handle(PacketEntityEquipment pkg) {
connection.getPlayer().getWorld().getEntity(pkg.getEntityId()).setEquipment(pkg.getSlot(), pkg.getData());
connection.getPlayer().getWorld().getEntity(pkg.getEntityId()).setEquipment(pkg.getSlots());
}
public void handle(PacketBlockChange pkg) {
@ -303,6 +307,8 @@ public class PacketHandler {
}
public void handle(PacketRespawn pkg) {
// clear all chunks
connection.getPlayer().getWorld().getAllChunks().clear();
connection.getPlayer().getWorld().setDimension(pkg.getDimension());
connection.getPlayer().setSpawnConfirmed(false);
connection.getPlayer().setGameMode(pkg.getGameMode());

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long