/* * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion * Copyright (C) 2016-2021 ViaVersion and contributors * * 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 . */ package com.viaversion.viaversion.protocols.protocol1_9to1_8.packets; import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.api.minecraft.entities.Entity1_10Types; import com.viaversion.viaversion.api.minecraft.item.Item; import com.viaversion.viaversion.api.minecraft.metadata.Metadata; import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_9; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.protocol.remapper.PacketHandler; import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper; import com.viaversion.viaversion.api.protocol.remapper.ValueCreator; import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer; import com.viaversion.viaversion.api.type.Type; import com.viaversion.viaversion.api.type.types.version.Types1_8; import com.viaversion.viaversion.api.type.types.version.Types1_9; import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8; import com.viaversion.viaversion.protocols.protocol1_9to1_8.ItemRewriter; import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8; import com.viaversion.viaversion.protocols.protocol1_9to1_8.metadata.MetadataRewriter1_9To1_8; import com.viaversion.viaversion.protocols.protocol1_9to1_8.storage.EntityTracker1_9; import java.util.ArrayList; import java.util.List; public class SpawnPackets { public static final ValueTransformer toNewDouble = new ValueTransformer(Type.DOUBLE) { @Override public Double transform(PacketWrapper wrapper, Integer inputValue) { return inputValue / 32D; } }; public static void register(Protocol1_9To1_8 protocol) { protocol.registerClientbound(ClientboundPackets1_8.SPAWN_ENTITY, new PacketRemapper() { @Override public void registerMap() { map(Type.VAR_INT); // 0 - Entity ID create(new ValueCreator() { @Override public void write(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); wrapper.write(Type.UUID, tracker.getEntityUUID(entityID)); // 1 - UUID } }); map(Type.BYTE); // 2 - Type // Parse this info handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); int typeID = wrapper.get(Type.BYTE, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); tracker.addEntity(entityID, Entity1_10Types.getTypeFromId(typeID, true)); tracker.sendMetadataBuffer(entityID); } }); map(Type.INT, toNewDouble); // 3 - X - Needs to be divide by 32 map(Type.INT, toNewDouble); // 4 - Y - Needs to be divide by 32 map(Type.INT, toNewDouble); // 5 - Z - Needs to be divide by 32 map(Type.BYTE); // 6 - Pitch map(Type.BYTE); // 7 - Yaw map(Type.INT); // 8 - Data // Create last 3 shorts create(new ValueCreator() { @Override public void write(PacketWrapper wrapper) throws Exception { int data = wrapper.get(Type.INT, 0); // Data (1st Integer) short vX = 0, vY = 0, vZ = 0; if (data > 0) { vX = wrapper.read(Type.SHORT); vY = wrapper.read(Type.SHORT); vZ = wrapper.read(Type.SHORT); } wrapper.write(Type.SHORT, vX); wrapper.write(Type.SHORT, vY); wrapper.write(Type.SHORT, vZ); } }); // Handle potions handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { final int entityID = wrapper.get(Type.VAR_INT, 0); final int data = wrapper.get(Type.INT, 0); // Data int typeID = wrapper.get(Type.BYTE, 0); if (Entity1_10Types.getTypeFromId(typeID, true) == Entity1_10Types.EntityType.SPLASH_POTION) { // Convert this to meta data, woo! PacketWrapper metaPacket = wrapper.create(0x39, new ValueCreator() { @Override public void write(PacketWrapper wrapper) throws Exception { wrapper.write(Type.VAR_INT, entityID); List meta = new ArrayList<>(); Item item = new Item(373, (byte) 1, (short) data, null); // Potion ItemRewriter.toClient(item); // Rewrite so that it gets the right nbt // TEMP FIX FOR POTIONS UNTIL WE FIGURE OUT HOW TO TRANSFORM SENT PACKETS Metadata potion = new Metadata(5, MetaType1_9.Slot, item); meta.add(potion); wrapper.write(Types1_9.METADATA_LIST, meta); } }); metaPacket.send(Protocol1_9To1_8.class); } } }); } }); protocol.registerClientbound(ClientboundPackets1_8.SPAWN_EXPERIENCE_ORB, new PacketRemapper() { @Override public void registerMap() { map(Type.VAR_INT); // 0 - Entity ID // Parse this info handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); tracker.addEntity(entityID, Entity1_10Types.EntityType.EXPERIENCE_ORB); tracker.sendMetadataBuffer(entityID); } }); map(Type.INT, toNewDouble); // 1 - X - Needs to be divide by 32 map(Type.INT, toNewDouble); // 2 - Y - Needs to be divide by 32 map(Type.INT, toNewDouble); // 3 - Z - Needs to be divide by 32 map(Type.SHORT); // 4 - Amount to spawn } }); protocol.registerClientbound(ClientboundPackets1_8.SPAWN_GLOBAL_ENTITY, new PacketRemapper() { @Override public void registerMap() { map(Type.VAR_INT); // 0 - Entity ID map(Type.BYTE); // 1 - Type // Parse this info handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { // Currently only lightning uses this int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); tracker.addEntity(entityID, Entity1_10Types.EntityType.LIGHTNING); tracker.sendMetadataBuffer(entityID); } }); map(Type.INT, toNewDouble); // 2 - X - Needs to be divide by 32 map(Type.INT, toNewDouble); // 3 - Y - Needs to be divide by 32 map(Type.INT, toNewDouble); // 4 - Z - Needs to be divide by 32 } }); protocol.registerClientbound(ClientboundPackets1_8.SPAWN_MOB, new PacketRemapper() { @Override public void registerMap() { map(Type.VAR_INT); // 0 - Entity ID create(new ValueCreator() { @Override public void write(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); wrapper.write(Type.UUID, tracker.getEntityUUID(entityID)); // 1 - UUID } }); map(Type.UNSIGNED_BYTE); // 2 - Type // Parse this info handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); int typeID = wrapper.get(Type.UNSIGNED_BYTE, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); tracker.addEntity(entityID, Entity1_10Types.getTypeFromId(typeID, false)); tracker.sendMetadataBuffer(entityID); } }); map(Type.INT, toNewDouble); // 3 - X - Needs to be divide by 32 map(Type.INT, toNewDouble); // 4 - Y - Needs to be divide by 32 map(Type.INT, toNewDouble); // 5 - Z - Needs to be divide by 32 map(Type.BYTE); // 6 - Yaw map(Type.BYTE); // 7 - Pitch map(Type.BYTE); // 8 - Head Pitch map(Type.SHORT); // 9 - Velocity X map(Type.SHORT); // 10 - Velocity Y map(Type.SHORT); // 11 - Velocity Z map(Types1_8.METADATA_LIST, Types1_9.METADATA_LIST); handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { List metadataList = wrapper.get(Types1_9.METADATA_LIST, 0); int entityId = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); if (tracker.hasEntity(entityId)) { protocol.get(MetadataRewriter1_9To1_8.class).handleMetadata(entityId, metadataList, wrapper.user()); } else { Via.getPlatform().getLogger().warning("Unable to find entity for metadata, entity ID: " + entityId); metadataList.clear(); } } }); // Handler for meta data handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { List metadataList = wrapper.get(Types1_9.METADATA_LIST, 0); int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); tracker.handleMetadata(entityID, metadataList); } }); } }); protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PAINTING, new PacketRemapper() { @Override public void registerMap() { map(Type.VAR_INT); // 0 - Entity ID // Parse this info handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); tracker.addEntity(entityID, Entity1_10Types.EntityType.PAINTING); tracker.sendMetadataBuffer(entityID); } }); create(new ValueCreator() { @Override public void write(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); wrapper.write(Type.UUID, tracker.getEntityUUID(entityID)); // 1 - UUID } }); map(Type.STRING); // 2 - Title map(Type.POSITION); // 3 - Position map(Type.BYTE); // 4 - Direction } }); protocol.registerClientbound(ClientboundPackets1_8.SPAWN_PLAYER, new PacketRemapper() { @Override public void registerMap() { map(Type.VAR_INT); // 0 - Entity ID map(Type.UUID); // 1 - Player UUID // Parse this info handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); tracker.addEntity(entityID, Entity1_10Types.EntityType.PLAYER); tracker.sendMetadataBuffer(entityID); } }); map(Type.INT, toNewDouble); // 2 - X - Needs to be divide by 32 map(Type.INT, toNewDouble); // 3 - Y - Needs to be divide by 32 map(Type.INT, toNewDouble); // 4 - Z - Needs to be divide by 32 map(Type.BYTE); // 5 - Yaw map(Type.BYTE); // 6 - Pitch handler(new PacketHandler() { //Handle discontinued player hand item @Override public void handle(PacketWrapper wrapper) throws Exception { short item = wrapper.read(Type.SHORT); if (item != 0) { PacketWrapper packet = PacketWrapper.create(0x3C, null, wrapper.user()); packet.write(Type.VAR_INT, wrapper.get(Type.VAR_INT, 0)); packet.write(Type.VAR_INT, 0); packet.write(Type.ITEM, new Item(item, (byte) 1, (short) 0, null)); try { packet.send(Protocol1_9To1_8.class, true, true); } catch (Exception e) { e.printStackTrace(); } } } }); map(Types1_8.METADATA_LIST, Types1_9.METADATA_LIST); handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { List metadataList = wrapper.get(Types1_9.METADATA_LIST, 0); int entityId = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); if (tracker.hasEntity(entityId)) { protocol.get(MetadataRewriter1_9To1_8.class).handleMetadata(entityId, metadataList, wrapper.user()); } else { Via.getPlatform().getLogger().warning("Unable to find entity for metadata, entity ID: " + entityId); metadataList.clear(); } } }); // Handler for meta data handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { List metadataList = wrapper.get(Types1_9.METADATA_LIST, 0); int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_9To1_8.class); tracker.handleMetadata(entityID, metadataList); } }); } }); protocol.registerClientbound(ClientboundPackets1_8.DESTROY_ENTITIES, new PacketRemapper() { @Override public void registerMap() { map(Type.VAR_INT_ARRAY_PRIMITIVE); // 0 - Entities to destroy handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { int[] entities = wrapper.get(Type.VAR_INT_ARRAY_PRIMITIVE, 0); for (int entity : entities) { // EntityTracker wrapper.user().getEntityTracker(Protocol1_9To1_8.class).removeEntity(entity); } } }); } }); } }