diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkBaseTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkBaseTranslator.java new file mode 100644 index 000000000..dff40ea75 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkBaseTranslator.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag; +import com.github.steveice10.opennbt.tag.builtin.ByteTag; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; +import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; +import org.geysermc.connector.utils.FireworkColor; +import org.geysermc.connector.utils.MathUtils; + +/** + * Stores common code for firework rockets and firework stars. + */ +public abstract class FireworkBaseTranslator extends NbtItemStackTranslator { + + protected CompoundTag translateExplosionToBedrock(CompoundTag explosion, String newName) { + CompoundTag newExplosionData = new CompoundTag(newName); + + if (explosion.get("Type") != null) { + newExplosionData.put(new ByteTag("FireworkType", MathUtils.convertByte(explosion.get("Type").getValue()))); + } + + if (explosion.get("Colors") != null) { + int[] oldColors = (int[]) explosion.get("Colors").getValue(); + byte[] colors = new byte[oldColors.length]; + + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } + + newExplosionData.put(new ByteArrayTag("FireworkColor", colors)); + } + + if (explosion.get("FadeColors") != null) { + int[] oldColors = (int[]) explosion.get("FadeColors").getValue(); + byte[] colors = new byte[oldColors.length]; + + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } + + newExplosionData.put(new ByteArrayTag("FireworkFade", colors)); + } + + if (explosion.get("Trail") != null) { + newExplosionData.put(new ByteTag("FireworkTrail", MathUtils.convertByte(explosion.get("Trail").getValue()))); + } + + if (explosion.get("Flicker") != null) { + newExplosionData.put(new ByteTag("FireworkFlicker", MathUtils.convertByte(explosion.get("Flicker").getValue()))); + } + + return newExplosionData; + } + + protected CompoundTag translateExplosionToJava(CompoundTag explosion, String newName) { + CompoundTag newExplosionData = new CompoundTag(newName); + + if (explosion.get("FireworkType") != null) { + newExplosionData.put(new ByteTag("Type", MathUtils.convertByte(explosion.get("FireworkType").getValue()))); + } + + if (explosion.get("FireworkColor") != null) { + byte[] oldColors = (byte[]) explosion.get("FireworkColor").getValue(); + int[] colors = new int[oldColors.length]; + + int i = 0; + for (byte color : oldColors) { + colors[i++] = FireworkColor.fromBedrockID(color).getJavaID(); + } + + newExplosionData.put(new IntArrayTag("Colors", colors)); + } + + if (explosion.get("FireworkFade") != null) { + byte[] oldColors = (byte[]) explosion.get("FireworkFade").getValue(); + int[] colors = new int[oldColors.length]; + + int i = 0; + for (byte color : oldColors) { + colors[i++] = FireworkColor.fromBedrockID(color).getJavaID(); + } + + newExplosionData.put(new IntArrayTag("FadeColors", colors)); + } + + if (explosion.get("FireworkTrail") != null) { + newExplosionData.put(new ByteTag("Trail", MathUtils.convertByte(explosion.get("FireworkTrail").getValue()))); + } + + if (explosion.get("FireworkFlicker") != null) { + newExplosionData.put(new ByteTag("Flicker", MathUtils.convertByte(explosion.get("FireworkFlicker").getValue()))); + } + + return newExplosionData; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkRocketTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkRocketTranslator.java new file mode 100644 index 000000000..f294315c8 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkRocketTranslator.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.ByteTag; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.utils.MathUtils; + +@ItemRemapper +public class FireworkRocketTranslator extends FireworkBaseTranslator { + + @Override + public void translateToBedrock(GeyserSession session, CompoundTag itemTag, ItemEntry itemEntry) { + CompoundTag fireworks = itemTag.get("Fireworks"); + if (fireworks == null) { + return; + } + + if (fireworks.get("Flight") != null) { + fireworks.put(new ByteTag("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue()))); + } + + ListTag explosions = fireworks.get("Explosions"); + if (explosions == null) { + return; + } + for (Tag effect : explosions.getValue()) { + CompoundTag effectData = (CompoundTag) effect; + CompoundTag newEffectData = translateExplosionToBedrock(effectData, ""); + + explosions.remove(effectData); + explosions.add(newEffectData); + } + } + + @Override + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + CompoundTag fireworks = itemTag.get("Fireworks"); + if (fireworks == null) { + return; + } + + if (fireworks.contains("Flight")) { + fireworks.put(new ByteTag("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue()))); + } + + ListTag explosions = fireworks.get("Explosions"); + if (explosions == null) { + return; + } + for (Tag effect : explosions.getValue()) { + CompoundTag effectData = (CompoundTag) effect; + CompoundTag newEffectData = translateExplosionToJava(effectData, ""); + + explosions.remove(effect); + explosions.add(newEffectData); + } + } + + @Override + public boolean acceptItem(ItemEntry itemEntry) { + return "minecraft:firework_rocket".equals(itemEntry.getJavaIdentifier()); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkStarTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkStarTranslator.java new file mode 100644 index 000000000..686887b45 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkStarTranslator.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; +import com.github.steveice10.opennbt.tag.builtin.IntTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.item.ItemEntry; + +@ItemRemapper +public class FireworkStarTranslator extends FireworkBaseTranslator { + + @Override + public void translateToBedrock(GeyserSession session, CompoundTag itemTag, ItemEntry itemEntry) { + Tag explosion = itemTag.get("Explosion"); + if (explosion instanceof CompoundTag) { + CompoundTag newExplosion = translateExplosionToBedrock((CompoundTag) explosion, "FireworksItem"); + itemTag.remove("Explosion"); + itemTag.put(newExplosion); + Tag color = ((CompoundTag) explosion).get("Colors"); + if (color instanceof IntArrayTag) { + // Determine the custom color, if any. + // Mostly replicates Java's own rendering code, as Java determines the final firework star color client-side + // while Bedrock determines it server-side. + int[] colors = ((IntArrayTag) color).getValue(); + if (colors.length == 0) { + return; + } + int finalColor; + if (colors.length == 1) { + finalColor = colors[0]; + } else { + int r = 0; + int g = 0; + int b = 0; + + for (int fireworkColor : colors) { + r += (fireworkColor & (255 << 16)) >> 16; + g += (fireworkColor & (255 << 8)) >> 8; + b += fireworkColor & 255; + } + + r /= colors.length; + g /= colors.length; + b /= colors.length; + finalColor = r << 16 | g << 8 | b; + } + + itemTag.put(new IntTag("customColor", finalColor)); + } + } + } + + @Override + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + Tag explosion = itemTag.get("FireworksItem"); + if (explosion instanceof CompoundTag) { + CompoundTag newExplosion = translateExplosionToJava((CompoundTag) explosion, "Explosion"); + itemTag.remove("FireworksItem"); + itemTag.put(newExplosion); + } + // Remove custom color, if any, since this only exists on Bedrock + itemTag.remove("customColor"); + } + + @Override + public boolean acceptItem(ItemEntry itemEntry) { + return "minecraft:firework_star".equals(itemEntry.getJavaIdentifier()); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java deleted file mode 100644 index 8c5b74f13..000000000 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser - */ - -package org.geysermc.connector.network.translators.item.translators.nbt; - -import com.github.steveice10.opennbt.tag.builtin.*; -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.item.ItemEntry; -import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; -import org.geysermc.connector.utils.FireworkColor; -import org.geysermc.connector.utils.MathUtils; - -@ItemRemapper -public class FireworkTranslator extends NbtItemStackTranslator { - - @Override - public void translateToBedrock(GeyserSession session, CompoundTag itemTag, ItemEntry itemEntry) { - if (!itemTag.contains("Fireworks")) { - return; - } - - CompoundTag fireworks = itemTag.get("Fireworks"); - if (fireworks.get("Flight") != null) { - fireworks.put(new ByteTag("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue()))); - } - - ListTag explosions = fireworks.get("Explosions"); - if (explosions == null) { - return; - } - for (Tag effect : explosions.getValue()) { - CompoundTag effectData = (CompoundTag) effect; - - CompoundTag newEffectData = new CompoundTag(""); - - if (effectData.get("Type") != null) { - newEffectData.put(new ByteTag("FireworkType", MathUtils.convertByte(effectData.get("Type").getValue()))); - } - - if (effectData.get("Colors") != null) { - int[] oldColors = (int[]) effectData.get("Colors").getValue(); - byte[] colors = new byte[oldColors.length]; - - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); - } - - newEffectData.put(new ByteArrayTag("FireworkColor", colors)); - } - - if (effectData.get("FadeColors") != null) { - int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); - byte[] colors = new byte[oldColors.length]; - - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); - } - - newEffectData.put(new ByteArrayTag("FireworkFade", colors)); - } - - if (effectData.get("Trail") != null) { - newEffectData.put(new ByteTag("FireworkTrail", MathUtils.convertByte(effectData.get("Trail").getValue()))); - } - - if (effectData.get("Flicker") != null) { - newEffectData.put(new ByteTag("FireworkFlicker", MathUtils.convertByte(effectData.get("Flicker").getValue()))); - } - - explosions.remove(effect); - explosions.add(newEffectData); - } - } - - @Override - public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { - if (!itemTag.contains("Fireworks")) { - return; - } - CompoundTag fireworks = itemTag.get("Fireworks"); - if (fireworks.contains("Flight")) { - fireworks.put(new ByteTag("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue()))); - } - - if (!itemTag.contains("Explosions")) { - return; - } - ListTag explosions = fireworks.get("Explosions"); - for (Tag effect : explosions.getValue()) { - CompoundTag effectData = (CompoundTag) effect; - - CompoundTag newEffectData = new CompoundTag(""); - - if (effectData.get("FireworkType") != null) { - newEffectData.put(new ByteTag("Type", MathUtils.convertByte(effectData.get("FireworkType").getValue()))); - } - - if (effectData.get("FireworkColor") != null) { - byte[] oldColors = (byte[]) effectData.get("FireworkColor").getValue(); - int[] colors = new int[oldColors.length]; - - int i = 0; - for (byte color : oldColors) { - colors[i++] = FireworkColor.fromBedrockID(color).getJavaID(); - } - - newEffectData.put(new IntArrayTag("Colors", colors)); - } - - if (effectData.get("FireworkFade") != null) { - byte[] oldColors = (byte[]) effectData.get("FireworkFade").getValue(); - int[] colors = new int[oldColors.length]; - - int i = 0; - for (byte color : oldColors) { - colors[i++] = FireworkColor.fromBedrockID(color).getJavaID(); - } - - newEffectData.put(new IntArrayTag("FadeColors", colors)); - } - - if (effectData.get("FireworkTrail") != null) { - newEffectData.put(new ByteTag("Trail", MathUtils.convertByte(effectData.get("FireworkTrail").getValue()))); - } - - if (effectData.get("FireworkFlicker") != null) { - newEffectData.put(new ByteTag("Flicker", MathUtils.convertByte(effectData.get("FireworkFlicker").getValue()))); - } - - explosions.remove(effect); - explosions.add(newEffectData); - } - } - - @Override - public boolean acceptItem(ItemEntry itemEntry) { - return "minecraft:firework_rocket".equals(itemEntry.getJavaIdentifier()); - } -}