diff --git a/README.md b/README.md index dc92764..4b1fb12 100644 --- a/README.md +++ b/README.md @@ -184,4 +184,4 @@ - [x] Villager trading - [ ] Accept trade _(Hard to implement, may require server plugin)_ - [x] Anvils -- [x] Chests \ No newline at end of file +- [x] Chests diff --git a/constants.js b/constants.js index f0d9e0d..0551bf3 100644 --- a/constants.js +++ b/constants.js @@ -1,17 +1,20 @@ -const GAME_PORT = 25565; -const WIN64_LAN_DISCOVERY_PORT = 25566; -const MINECRAFT_NET_VERSION = 560; -const JAVA_SERVER_HOST = "localhost"; -const JAVA_SERVER_PORT = 25564; -const PROXY_NAME = JAVA_SERVER_HOST + ":" + JAVA_SERVER_PORT; - -module.exports = { - GAME_PORT, - WIN64_LAN_DISCOVERY_PORT, - MINECRAFT_NET_VERSION, - USE_LEGACY_USERNAME: false, // you can use your legacy edition username, or a custom username below. - CUSTOM_USERNAME: "LCE_Player", - JAVA_SERVER_HOST, - JAVA_SERVER_PORT, - PROXY_NAME, -}; \ No newline at end of file +/* --------------------------------------------------------------- */ +/* constants.js */ +/* --------------------------------------------------------------- */ +const GAME_PORT = 25565; // +const WIN64_LAN_DISCOVERY_PORT = 25566; // +const MINECRAFT_NET_VERSION = 560; // +const JAVA_SERVER_HOST = "localhost"; // The java edition server host that the proxy will connect to. +const JAVA_SERVER_PORT = 25564; // The java edition server port that the proxy will connect to (default is 25565). +const PROXY_NAME = JAVA_SERVER_HOST + ":" + JAVA_SERVER_PORT; // +module.exports = { // + GAME_PORT, // + WIN64_LAN_DISCOVERY_PORT, // + MINECRAFT_NET_VERSION, // + USE_LEGACY_USERNAME: false, // You can use your legacy edition username, or a custom username below. + CUSTOM_USERNAME: "LCE_Player", // The custom username used if USE_LEGACY_USERNAME is false. Ensure it's UNDER 16 characters. + JAVA_SERVER_HOST, // + JAVA_SERVER_PORT, // + PROXY_NAME, // +}; // +/* --------------------------------------------------------------- */ \ No newline at end of file diff --git a/index.js b/index.js index a61b37b..8db2f73 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* index.js */ +/* --------------------------------------------------------------- */ process.removeAllListeners("warning"); process.on("warning", (warning) => { if (warning.name === "DeprecationWarning") return; @@ -12,4 +15,5 @@ proxy.start(); process.on("SIGINT", () => { proxy.stop(); process.exit(0); -}); \ No newline at end of file +}); +/* --------------------------------------------------------------- */ diff --git a/src/JavaClientHandler.js b/src/JavaClientHandler.js index d1c2078..7ccd502 100644 --- a/src/JavaClientHandler.js +++ b/src/JavaClientHandler.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* javaclienthandler.js */ +/* --------------------------------------------------------------- */ const mc = require("minecraft-protocol"); const { JAVA_SERVER_HOST, @@ -5,9 +8,9 @@ const { USE_LEGACY_USERNAME, CUSTOM_USERNAME, } = require("../constants"); -const PacketWriter = require("./PacketWriter"); +const PacketWriter = require("./packetwriter"); const { mapJavaItemToLCE, mapJavaBlockToLCE } = require("./mappings"); -const { mapJavaSoundToLCE } = require("./mappings/soundMapping"); +const { mapJavaSoundToLCE } = require("./mappings/soundmapping"); const { parseChatComponent } = require("./utils/chat"); const { countSetBits, compressRLE } = require("./utils/chunk"); const zlib = require("zlib"); @@ -572,7 +575,8 @@ function connectToJavaServer(proxy, client) { javaClient.on("custom_payload", (packet) => { if (client.state === "play" && packet.channel === "MC|TrList") { - proxy.sendVillagerTrades(client, packet.data); + const windowId = client.openWindowId || 1; + proxy.sendVillagerTrades(client, windowId, packet.data); } }); @@ -2073,4 +2077,5 @@ function convertAndSendJavaChunk(proxy, client, javaChunk) { proxy.sendPacket(client, 0x33, fullPayload); } -module.exports = connectToJavaServer; \ No newline at end of file +module.exports = connectToJavaServer; +/* --------------------------------------------------------------- */ diff --git a/src/LANBroadcast.js b/src/LANBroadcast.js index 36d5349..34dfb38 100644 --- a/src/LANBroadcast.js +++ b/src/LANBroadcast.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* lanbroadcast.js */ +/* --------------------------------------------------------------- */ const { MINECRAFT_NET_VERSION, GAME_PORT, @@ -26,4 +29,5 @@ class LANBroadcast { } } -module.exports = LANBroadcast; \ No newline at end of file +module.exports = LANBroadcast; +/* --------------------------------------------------------------- */ diff --git a/src/LCEProxy.js b/src/LCEProxy.js index 8df8238..b137949 100644 --- a/src/LCEProxy.js +++ b/src/LCEProxy.js @@ -1,4 +1,7 @@ -const dgram = require("dgram"); +/* --------------------------------------------------------------- */ +/* lceproxy.js */ +/* --------------------------------------------------------------- */ +const dgram = require("dgram"); const net = require("net"); const mc = require("minecraft-protocol"); const { @@ -9,9 +12,9 @@ const { CUSTOM_USERNAME, PROXY_NAME, } = require("../constants"); -const PacketWriter = require("./PacketWriter"); -const PacketReader = require("./PacketReader"); -const LANBroadcast = require("./LANBroadcast"); +const PacketWriter = require("./packetwriter"); +const PacketReader = require("./packetreader"); +const LANBroadcast = require("./lanbroadcast"); const { createEntityTypeMapping, createItemMapping, @@ -23,7 +26,7 @@ const { normalizeYaw } = require("./utils/rotation"); const { readItemInstance } = require("./utils/items"); const { readItem, writeItem, writeItemNBT } = require("./utils/items"); const packetSenders = require("./packets/senders"); -const connectToJavaServerFunc = require("./JavaClientHandler"); +const connectToJavaServerFunc = require("./javaclienthandler"); //please stfu node process.removeAllListeners("warning"); @@ -1009,6 +1012,10 @@ class LCEProxy { return packetSenders.sendContainerOpenPacket(this, client, packet); } + sendVillagerTrades(client, windowId, packetData) { + return packetSenders.sendVillagerTrades(this, client, windowId, packetData); + } + //debug sendFlatChunk(client, chunkX, chunkZ) { const xs = 16; @@ -2172,7 +2179,7 @@ class LCEProxy { const uid = reader.readShort(); const clickType = reader.readByte(); - const item = this.readItem(reader); + const item = this.readItemWithNBT(reader); //0=Normal click //1=Shift click @@ -2191,6 +2198,9 @@ class LCEProxy { itemCount: item.itemCount, itemDamage: item.itemDamage, }; + if (item.nbt) { + javaItem.nbtData = this.convertLCENBTToJava(item.nbt); + } } } @@ -2218,7 +2228,7 @@ class LCEProxy { handleSetCreativeModeSlot(client, data) { const reader = new PacketReader(data.slice(1)); const slotNum = reader.readShort(); - const item = this.readItem(reader); + const item = this.readItemWithNBT(reader); let javaItem = null; if (item) { @@ -2227,8 +2237,11 @@ class LCEProxy { javaItem = { blockId: javaItemId, itemCount: item.itemCount, - itemDamage: item.itemDamage, + itemDamage: 0, }; + if (item.nbt) { + javaItem.nbtData = this.convertLCENBTToJava(item.nbt); + } } } @@ -2359,6 +2372,90 @@ class LCEProxy { return readItem(reader); } + readItemWithNBT(reader) { + const itemId = reader.readShort(); + if (itemId === -1) { + return null; + } + const count = reader.readByte(); + const damage = reader.readShort(); + + if (reader.offset + 2 > reader.buffer.length) { + return { + blockId: itemId, + itemCount: count, + itemDamage: damage, + nbt: null + }; + } + + const nbtLength = reader.readShort(); + + let nbt = null; + if (nbtLength > 0 && reader.offset + nbtLength <= reader.buffer.length) { + const nbtBytes = reader.readBytes(nbtLength); + nbt = nbtBytes; + } + + return { + blockId: itemId, + itemCount: count, + itemDamage: damage, + nbt: nbt + }; + } + + convertLCENBTToJava(nbtBytes) { + try { + const zlib = require('zlib'); + const decompressed = zlib.gunzipSync(nbtBytes); + const nbtReader = new PacketReader(decompressed); + const rootTag = this.readNBTTag(nbtReader); + return rootTag; + } catch (err) { + return null; + } + } + + readNBTTag(reader) { + const type = reader.readByte(); + if (type === 0) return null; + const name = reader.readUTF(); + return this.readNBTPayload(reader, type, name); + } + + readNBTPayload(reader, type, name) { + switch (type) { + case 1: + return { type: 'byte', name, value: reader.readByte() }; + case 2: + return { type: 'short', name, value: reader.readShort() }; + case 3: + return { type: 'int', name, value: reader.readInt() }; + case 8: + return { type: 'string', name, value: reader.readUTF() }; + case 9: + const listType = reader.readByte(); + const listSize = reader.readInt(); + const listItems = []; + for (let i = 0; i < listSize; i++) { + listItems.push(this.readNBTPayload(reader, listType, '')); + } + return { type: 'list', name, value: { type: listType, value: listItems } }; + case 10: + const compound = {}; + while (true) { + const tagType = reader.readByte(); + if (tagType === 0) break; + const tagName = reader.readUTF(); + compound[tagName] = this.readNBTPayload(reader, tagType, tagName); + } + return { type: 'compound', name, value: compound }; + default: + return null; + } + } + writeItemNBT(writer, item) { return writeItemNBT(writer, item); } @@ -2451,4 +2548,5 @@ class LCEProxy { } } -module.exports = LCEProxy; \ No newline at end of file +module.exports = LCEProxy; +/* --------------------------------------------------------------- */ diff --git a/src/PacketReader.js b/src/PacketReader.js index 67f6fb5..e75da1c 100644 --- a/src/PacketReader.js +++ b/src/PacketReader.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* packetreader.js */ +/* --------------------------------------------------------------- */ class PacketReader { constructor(buffer) { this.buffer = buffer; @@ -72,4 +75,5 @@ class PacketReader { } } -module.exports = PacketReader; \ No newline at end of file +module.exports = PacketReader; +/* --------------------------------------------------------------- */ diff --git a/src/PacketWriter.js b/src/PacketWriter.js index de9fe16..82a3a2d 100644 --- a/src/PacketWriter.js +++ b/src/PacketWriter.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* packetwriter.js */ +/* --------------------------------------------------------------- */ class PacketWriter { constructor() { this.buffers = []; @@ -86,4 +89,5 @@ class PacketWriter { } } -module.exports = PacketWriter; \ No newline at end of file +module.exports = PacketWriter; +/* --------------------------------------------------------------- */ diff --git a/src/mappings/blockMapping.js b/src/mappings/blockMapping.js index e8cd6a4..467f0a2 100644 --- a/src/mappings/blockMapping.js +++ b/src/mappings/blockMapping.js @@ -1,4 +1,7 @@ -function createBlockMapping() { +/* --------------------------------------------------------------- */ +/* blockmapping.js */ +/* --------------------------------------------------------------- */ +function createBlockMapping() { return { 0: 0, 1: 1, @@ -173,4 +176,5 @@ }; } -module.exports = { createBlockMapping }; \ No newline at end of file +module.exports = { createBlockMapping }; +/* --------------------------------------------------------------- */ diff --git a/src/mappings/entityMapping.js b/src/mappings/entityMapping.js index 01bc901..45aacfb 100644 --- a/src/mappings/entityMapping.js +++ b/src/mappings/entityMapping.js @@ -1,4 +1,7 @@ -function createEntityTypeMapping() { +/* --------------------------------------------------------------- */ +/* entitymapping.js */ +/* --------------------------------------------------------------- */ +function createEntityTypeMapping() { return { //monsters Creeper: 50, @@ -64,4 +67,5 @@ }; } -module.exports = { createEntityTypeMapping }; \ No newline at end of file +module.exports = { createEntityTypeMapping }; +/* --------------------------------------------------------------- */ diff --git a/src/mappings/idMappers.js b/src/mappings/idmapper.js similarity index 70% rename from src/mappings/idMappers.js rename to src/mappings/idmapper.js index 9738a8d..aef787c 100644 --- a/src/mappings/idMappers.js +++ b/src/mappings/idmapper.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* idmappers.js */ +/* --------------------------------------------------------------- */ const { mapJavaBlockToLCE: mapBlockId } = require("./mappers"); function mapJavaEntityIdToLce(client, javaEntityId) { @@ -24,4 +27,5 @@ module.exports = { mapJavaEntityIdToLce, mapJavaBlockToLCE, mapJavaParticleToLCE, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/mappings/index.js b/src/mappings/index.js index 59284c2..1232d8c 100644 --- a/src/mappings/index.js +++ b/src/mappings/index.js @@ -1,6 +1,9 @@ -const { createEntityTypeMapping } = require("./entityMapping"); -const { createItemMapping } = require("./itemMapping"); -const { createBlockMapping } = require("./blockMapping"); +/* --------------------------------------------------------------- */ +/* index.js */ +/* --------------------------------------------------------------- */ +const { createEntityTypeMapping } = require("./entitymapping"); +const { createItemMapping } = require("./itemmapping"); +const { createBlockMapping } = require("./blockmapping"); const { mapJavaBlockToLCE, mapJavaParticleToLCE, @@ -18,4 +21,5 @@ module.exports = { mapJavaItemToLCE, mapLCEItemToJava, mapLCEBlockToJava, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/mappings/itemMapping.js b/src/mappings/itemMapping.js index b262668..1ba7e8f 100644 --- a/src/mappings/itemMapping.js +++ b/src/mappings/itemMapping.js @@ -1,4 +1,7 @@ -function createItemMapping() { +/* --------------------------------------------------------------- */ +/* itemmapping.js */ +/* --------------------------------------------------------------- */ +function createItemMapping() { return { 256: 256, //iron_shovel 257: 257, //iron_pickaxe @@ -172,3 +175,4 @@ } module.exports = { createItemMapping }; +/* --------------------------------------------------------------- */ diff --git a/src/mappings/mappers.js b/src/mappings/mappers.js index 74cc1c3..7d46153 100644 --- a/src/mappings/mappers.js +++ b/src/mappings/mappers.js @@ -1,4 +1,7 @@ -function mapJavaBlockToLCE(javaBlockId, javaBlockMapping) { +/* --------------------------------------------------------------- */ +/* mappers.js */ +/* --------------------------------------------------------------- */ +function mapJavaBlockToLCE(javaBlockId, javaBlockMapping) { if (javaBlockMapping[javaBlockId] !== undefined) { return javaBlockMapping[javaBlockId]; } @@ -118,4 +121,5 @@ module.exports = { mapJavaItemToLCE, mapLCEItemToJava, mapLCEBlockToJava, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/mappings/soundMapping.js b/src/mappings/soundMapping.js index 8c88d29..8d3fb07 100644 --- a/src/mappings/soundMapping.js +++ b/src/mappings/soundMapping.js @@ -1,4 +1,7 @@ -function mapJavaSoundToLCE(soundName) { +/* --------------------------------------------------------------- */ +/* soundmapping.js */ +/* --------------------------------------------------------------- */ +function mapJavaSoundToLCE(soundName) { const soundMap = { "mob.chicken.say": 0, "mob.chicken": 0, @@ -226,4 +229,5 @@ return result !== undefined ? result : -1; } -module.exports = { mapJavaSoundToLCE }; \ No newline at end of file +module.exports = { mapJavaSoundToLCE }; +/* --------------------------------------------------------------- */ diff --git a/src/packets/senders/containerPackets.js b/src/packets/senders/containerPackets.js index a11170e..9f67591 100644 --- a/src/packets/senders/containerPackets.js +++ b/src/packets/senders/containerPackets.js @@ -1,20 +1,23 @@ -const PacketWriter = require("../../PacketWriter"); +/* --------------------------------------------------------------- */ +/* containerpackets.js */ +/* --------------------------------------------------------------- */ +const PacketWriter = require("../../packetwriter"); function sendContainerOpenPacket(proxy, client, packet) { const windowTypeMapping = { - "minecraft:container": 0, //container - "minecraft:chest": 0, //container - "minecraft:crafting_table": 1, //workbench - "minecraft:furnace": 2, //furnace - "minecraft:dispenser": 3, //trap - "minecraft:enchanting_table": 4, //enchantment - "minecraft:brewing_stand": 5, //brewing_stand - "minecraft:villager": 6, //trader npc - "minecraft:beacon": 7, //beacon - "minecraft:anvil": 8, //repair table - "minecraft:hopper": 9, //hopper - "minecraft:dropper": 10, //dropper - "minecraft:horse": 11, //horse + "minecraft:container": 0, //container + "minecraft:chest": 0, //container + "minecraft:crafting_table": 1, //workbench + "minecraft:furnace": 2, //furnace + "minecraft:dispenser": 3, //trap + "minecraft:enchanting_table": 4, //enchantment + "minecraft:brewing_stand": 5, //brewing_stand + "minecraft:villager": 6, //trader npc + "minecraft:beacon": 7, //beacon + "minecraft:anvil": 8, //repair table + "minecraft:hopper": 9, //hopper + "minecraft:dropper": 10, //dropper + "minecraft:horse": 11, //horse }; const windowType = packet.inventoryType || packet.windowType; @@ -32,7 +35,8 @@ function sendContainerOpenPacket(proxy, client, packet) { writer.writeByte(size & 0xff); writer.writeBoolean(customName); - if (lceType === 11) { //horse + if (lceType === 11) { + //horse writer.writeInt(packet.entityId || 0); } @@ -43,6 +47,134 @@ function sendContainerOpenPacket(proxy, client, packet) { proxy.sendPacket(client, 0x64, writer.toBuffer()); } +function sendVillagerTrades(proxy, client, windowId, packetData) { + const PacketReader = require("../../packetreader"); + const reader = new PacketReader(packetData); + reader.readInt(); + const numTrades = reader.readByte(); + + const trades = []; + for (let i = 0; i < numTrades; i++) { + const trade = {}; + trade.input1 = readTradeItem(reader); + trade.output = readTradeItem(reader); + const hasSecondItem = reader.readByte() !== 0; + if (hasSecondItem) { + trade.input2 = readTradeItem(reader); + } + reader.readByte(); + trade.uses = reader.readInt(); + trade.maxUses = reader.readInt(); + trades.push(trade); + } + + const payloadWriter = new PacketWriter(); + payloadWriter.writeInt(windowId); + payloadWriter.writeByte(trades.length & 0xff); + + for (const trade of trades) { + writeItemToBuffer(payloadWriter, trade.input1); + writeItemToBuffer(payloadWriter, trade.output); + payloadWriter.writeBoolean( + trade.input2 !== null && trade.input2 !== undefined, + ); + if (trade.input2) { + writeItemToBuffer(payloadWriter, trade.input2); + } + payloadWriter.writeBoolean(trade.disabled || false); + payloadWriter.writeInt(trade.uses || 0); + payloadWriter.writeInt(trade.maxUses || 7); + } + + const customWriter = new PacketWriter(); + customWriter.writeUtf("MC|TrList"); + customWriter.writeShort(payloadWriter.toBuffer().length); + customWriter.writeBytes(payloadWriter.toBuffer()); + + proxy.sendPacket(client, 0xfa, customWriter.toBuffer()); +} + +function readTradeItem(reader) { + const id = reader.readShort(); + if (id === -1) { + return null; + } + const count = reader.readByte(); + const damage = reader.readShort(); + const tagType = reader.readByte(); + if (tagType !== 0) { + skipNBT(reader, tagType); + } + return { blockId: id, itemCount: count, itemDamage: damage }; +} + +function skipNBT(reader, tagType) { + switch (tagType) { + case 0: + return; + case 1: + reader.readByte(); + return; + case 2: + reader.readShort(); + return; + case 3: + reader.readInt(); + return; + case 4: + reader.readInt(); + reader.readInt(); + return; + case 5: + reader.readFloat(); + return; + case 6: + reader.readDouble(); + return; + case 7: + const byteArrLen = reader.readInt(); + reader.offset += byteArrLen; + return; + case 8: + const strLen = reader.readShort(); + reader.offset += strLen; + return; + case 9: + const childType = reader.readByte(); + const listLen = reader.readInt(); + for (let i = 0; i < listLen; i++) { + skipNBT(reader, childType); + } + return; + case 10: + while (true) { + const type = reader.readByte(); + if (type === 0) break; + const nameLen = reader.readShort(); + reader.offset += nameLen; + skipNBT(reader, type); + } + return; + case 11: + const arrLen = reader.readInt(); + reader.offset += arrLen * 4; + return; + } +} + +function writeItemToBuffer(writer, item) { + if (!item) { + writer.writeShort(-1); + return; + } + writer.writeShort(item.blockId); + writer.writeByte(item.itemCount & 0xff); + writer.writeShort(item.itemDamage || 0); + writer.writeShort(-1); +} + module.exports = { sendContainerOpenPacket, -}; \ No newline at end of file + sendVillagerTrades, +}; +/* --------------------------------------------------------------- */ diff --git a/src/packets/senders/entityPackets.js b/src/packets/senders/entityPackets.js index deab4e8..a57bf33 100644 --- a/src/packets/senders/entityPackets.js +++ b/src/packets/senders/entityPackets.js @@ -1,4 +1,7 @@ -const PacketWriter = require("../../PacketWriter"); +/* --------------------------------------------------------------- */ +/* entitypackets.js */ +/* --------------------------------------------------------------- */ +const PacketWriter = require("../../packetwriter"); function sendAddMobPacket(proxy, client, entityInfo) { const entityKey = `${entityInfo.javaEntityId}`; @@ -541,4 +544,5 @@ module.exports = { sendSetEntityDataPacket, sendUpdateAttributesPacket, sendSetEntityLinkPacket, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/packets/senders/index.js b/src/packets/senders/index.js index 040b778..e125bfe 100644 --- a/src/packets/senders/index.js +++ b/src/packets/senders/index.js @@ -1,11 +1,15 @@ -const playerPackets = require("./playerPackets"); -const entityPackets = require("./entityPackets"); +/* --------------------------------------------------------------- */ +/* index.js */ +/* --------------------------------------------------------------- */ +const playerPackets = require("./playerpackets"); +const entityPackets = require("./entitypackets"); const worldPackets = require("./worldPackets"); -const containerPackets = require("./containerPackets"); +const containerPackets = require("./containerpackets"); module.exports = { ...playerPackets, ...entityPackets, ...worldPackets, ...containerPackets, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/packets/senders/playerPackets.js b/src/packets/senders/playerPackets.js index b2a69ab..b4b2077 100644 --- a/src/packets/senders/playerPackets.js +++ b/src/packets/senders/playerPackets.js @@ -1,4 +1,7 @@ -const PacketWriter = require("../../PacketWriter"); +/* --------------------------------------------------------------- */ +/* playerpackets.js */ +/* --------------------------------------------------------------- */ +const PacketWriter = require("../../packetwriter"); function sendMovePlayerPacket(proxy, client, x, y, z, yaw, pitch) { const lceY = y + 1.65; @@ -112,4 +115,5 @@ module.exports = { sendTeleportEntityPacket, sendRotateHeadPacket, sendChatPacket, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/packets/senders/worldPackets.js b/src/packets/senders/worldPackets.js index 9301c31..45f44c7 100644 --- a/src/packets/senders/worldPackets.js +++ b/src/packets/senders/worldPackets.js @@ -1,4 +1,7 @@ -const PacketWriter = require("../../PacketWriter"); +/* --------------------------------------------------------------- */ +/* worldpackets.js */ +/* --------------------------------------------------------------- */ +const PacketWriter = require("../../packetwriter"); function sendLevelSoundPacket(proxy, client, soundId, x, y, z, volume, pitch) { const safeX = x !== undefined && x !== null && !isNaN(x) ? x : 0; @@ -69,4 +72,5 @@ module.exports = { sendLevelSoundPacket, sendLevelParticlesPacket, sendTileUpdatePacket, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/utils.js b/src/utils.js index 4a4faa1..b14b6eb 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* utils.js */ +/* --------------------------------------------------------------- */ function encodeVarInt(value) { const bytes = []; do { @@ -13,4 +16,5 @@ function encodeVarInt(value) { module.exports = { encodeVarInt, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/utils/chat.js b/src/utils/chat.js index a83912d..2ce6a86 100644 --- a/src/utils/chat.js +++ b/src/utils/chat.js @@ -1,4 +1,7 @@ -function getTranslation(key, args = []) { +/* --------------------------------------------------------------- */ +/* chat.js */ +/* --------------------------------------------------------------- */ +function getTranslation(key, args = []) { const translations = { "chat.type.text": (args) => `<${args[0]}> ${args[1]}`, "chat.type.announcement": (args) => `[${args[0]}] ${args[1]}`, @@ -520,4 +523,5 @@ function parseChatComponent(component) { return result; } -module.exports = { getTranslation, parseChatComponent }; \ No newline at end of file +module.exports = { getTranslation, parseChatComponent }; +/* --------------------------------------------------------------- */ diff --git a/src/utils/chunk.js b/src/utils/chunk.js index ccac770..2a8698f 100644 --- a/src/utils/chunk.js +++ b/src/utils/chunk.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* chunk.js */ +/* --------------------------------------------------------------- */ function compressRLE(data) { const output = []; let i = 0; @@ -40,4 +43,5 @@ function countSetBits(n) { module.exports = { compressRLE, countSetBits, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/utils/items.js b/src/utils/items.js index 30e9e7a..9737dce 100644 --- a/src/utils/items.js +++ b/src/utils/items.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* items.js */ +/* --------------------------------------------------------------- */ function readSlot(reader) { const id = reader.readShort(); if (id === -1 || id === 0) { @@ -48,36 +51,51 @@ function readItem(reader) { const count = reader.readByte(); const damage = reader.readShort(); + const nbtSize = reader.readShort(); + let nbtData = null; + if (nbtSize > 0) { + const nbtBytes = reader.readBytes(nbtSize); + nbtData = { raw: nbtBytes }; + } + return { blockId: itemId, itemCount: count, itemDamage: damage, + nbtData: nbtData, }; } function writeItemNBT(writer, item) { - const PacketWriter = require("../PacketWriter"); + const PacketWriter = require("../packetwriter"); let customName = null; + let storedEnchantments = null; - if (item.nbtData && item.nbtData.value && item.nbtData.value.display) { - const display = item.nbtData.value.display.value; - if (display.Name) { - customName = display.Name.value; - try { - const parsed = JSON.parse(customName); - if (parsed.text) { - customName = parsed.text; - } else if (typeof parsed === "string") { - customName = parsed; + if (item.nbtData && item.nbtData.value) { + if (item.nbtData.value.display) { + const display = item.nbtData.value.display.value; + if (display.Name) { + customName = display.Name.value; + try { + const parsed = JSON.parse(customName); + if (parsed.text) { + customName = parsed.text; + } else if (typeof parsed === "string") { + customName = parsed; + } + } catch (err) { + /* do nothing */ } - } catch (err) { - /* do nothing */ } } + + if (item.nbtData.value.StoredEnchantments) { + storedEnchantments = item.nbtData.value.StoredEnchantments.value.value; + } } - if (!customName) { + if (!customName && !storedEnchantments) { writer.writeShort(-1); return; } @@ -87,14 +105,31 @@ function writeItemNBT(writer, item) { nbtWriter.writeByte(10); nbtWriter.writeUTF(""); - nbtWriter.writeByte(10); - nbtWriter.writeUTF("display"); + if (customName) { + nbtWriter.writeByte(10); + nbtWriter.writeUTF("display"); + nbtWriter.writeByte(8); + nbtWriter.writeUTF("Name"); + nbtWriter.writeUTF(customName); + nbtWriter.writeByte(0); + } - nbtWriter.writeByte(8); - nbtWriter.writeUTF("Name"); - nbtWriter.writeUTF(customName); + if (storedEnchantments) { + nbtWriter.writeByte(9); + nbtWriter.writeUTF("StoredEnchantments"); + nbtWriter.writeByte(10); + nbtWriter.writeInt(storedEnchantments.length); - nbtWriter.writeByte(0); + for (const ench of storedEnchantments) { + nbtWriter.writeByte(2); + nbtWriter.writeUTF("id"); + nbtWriter.writeShort(ench.id.value); + nbtWriter.writeByte(2); + nbtWriter.writeUTF("lvl"); + nbtWriter.writeShort(ench.lvl.value); + nbtWriter.writeByte(0); + } + } nbtWriter.writeByte(0); @@ -156,4 +191,5 @@ module.exports = { readItem, writeItemNBT, writeItem, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/utils/rotation.js b/src/utils/rotation.js index df39b6f..d2fd798 100644 --- a/src/utils/rotation.js +++ b/src/utils/rotation.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* rotation.js */ +/* --------------------------------------------------------------- */ function normalizeYaw(yaw) { let normalized = yaw % 360; if (normalized > 180) { @@ -10,4 +13,5 @@ function normalizeYaw(yaw) { module.exports = { normalizeYaw, -}; \ No newline at end of file +}; +/* --------------------------------------------------------------- */ diff --git a/src/utils/translations.js b/src/utils/translations.js index a7ef926..a3cc5d6 100644 --- a/src/utils/translations.js +++ b/src/utils/translations.js @@ -1,3 +1,6 @@ +/* --------------------------------------------------------------- */ +/* translations.js */ +/* --------------------------------------------------------------- */ function getTranslation(key, args = []) { const translations = {}; @@ -12,4 +15,5 @@ function getTranslation(key, args = []) { return key; } -module.exports = { getTranslation }; \ No newline at end of file +module.exports = { getTranslation }; +/* --------------------------------------------------------------- */