Skip to content

Commit

Permalink
Keep chugging away
Browse files Browse the repository at this point in the history
  • Loading branch information
Camotoy committed Apr 20, 2024
1 parent 54f04b5 commit 78edbac
Show file tree
Hide file tree
Showing 26 changed files with 200 additions and 184 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,21 @@

package org.geysermc.geyser.item;

import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
import com.github.steveice10.mc.protocol.data.game.item.component.DyedItemColor;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;

public interface DyeableLeatherItem {

static void translateNbtToBedrock(CompoundTag tag) {
CompoundTag displayTag = tag.get("display");
if (displayTag == null) {
static void translateComponentsToBedrock(DataComponents components, BedrockItemBuilder builder) {
DyedItemColor dyedItemColor = components.get(DataComponentType.DYED_COLOR);
if (dyedItemColor == null) {
return;
}
IntTag color = displayTag.remove("color");
if (color != null) {
tag.put(new IntTag("customColor", color.getValue()));
}
builder.putInt("customColor", dyedItemColor.getRgb());
}

static void translateNbtToJava(CompoundTag tag) {
Expand Down
25 changes: 16 additions & 9 deletions core/src/main/java/org/geysermc/geyser/item/type/ArmorItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@

package org.geysermc.geyser.item.type;

import com.github.steveice10.mc.protocol.data.game.item.component.ArmorTrim;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.item.ArmorMaterial;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;

public class ArmorItem extends Item {
private final ArmorMaterial material;
Expand All @@ -43,23 +47,26 @@ public ArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder)
}

@Override
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) {
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder);

if (tag.get("Trim") instanceof CompoundTag trim) {
StringTag material = trim.remove("material");
StringTag pattern = trim.remove("pattern");
ArmorTrim trim = components.get(DataComponentType.TRIM);
if (trim != null) {
// TODO material IDs
String material = trim.getMaterial().getAssetName();
String pattern = trim.getPattern().getAssetId();

// discard custom trim patterns/materials to prevent visual glitches on bedrock
if (!material.getValue().startsWith("minecraft:")
|| !pattern.getValue().startsWith("minecraft:")) {
tag.remove("Trim");
if (!material.startsWith("minecraft:")
|| !pattern.startsWith("minecraft:")) {
return;
}

NbtMapBuilder trimBuilder = NbtMap.builder();
// bedrock has an uppercase first letter key, and the value is not namespaced
trim.put(new StringTag("Material", stripNamespace(material.getValue())));
trim.put(new StringTag("Pattern", stripNamespace(pattern.getValue())));
trimBuilder.put("Material", stripNamespace(material));
trimBuilder.put("Pattern", stripNamespace(pattern));
builder.putCompound("Trim", trimBuilder.build());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,26 @@
package org.geysermc.geyser.item.type;

import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
import com.github.steveice10.opennbt.tag.builtin.ByteTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;

public class AxolotlBucketItem extends Item {
public AxolotlBucketItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}

@Override
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) {
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder);

// Bedrock Edition displays the properties of the axolotl. Java does not.
// To work around this, set the custom name to the Axolotl translation and it's displayed correctly
tag.put(new ByteTag("AppendCustomName", (byte) 1));
tag.put(new StringTag("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.axolotl", session.locale())));
builder.putByte("AppendCustomName", 1);
builder.putString("CustomName", MinecraftLocale.getLocaleString("entity.minecraft.axolotl", session.locale()));
// Boilerplate required so the nametag does not appear as "Bucket of "
tag.put(new StringTag("ColorID", ""));
tag.put(new StringTag("BodyID", ""));
builder.putString("ColorID", "");
builder.putString("BodyID", "");
}
}
37 changes: 19 additions & 18 deletions core/src/main/java/org/geysermc/geyser/item/type/BannerItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

package org.geysermc.geyser.item.type;

import com.github.steveice10.mc.protocol.data.game.item.component.BannerPatternLayer;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
Expand All @@ -33,16 +35,14 @@
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;

import java.util.ArrayList;
import java.util.List;

import static org.geysermc.erosion.util.BannerUtils.getJavaPatternTag;

public class BannerItem extends BlockItem {
/**
* Holds what a Java ominous banner pattern looks like.
Expand All @@ -51,19 +51,20 @@ public class BannerItem extends BlockItem {
* ominous banners that we set instead. This variable is used to detect Java ominous banner patterns, and apply
* the correct ominous banner pattern if Bedrock pulls the item from creative.
*/
public static final ListTag OMINOUS_BANNER_PATTERN;
public static final List<BannerPatternLayer> OMINOUS_BANNER_PATTERN;

static {
OMINOUS_BANNER_PATTERN = new ListTag("Patterns");
// Construct what an ominous banner is supposed to look like
OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("mr", 9));
OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("bs", 8));
OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("cs", 7));
OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("bo", 8));
OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("ms", 15));
OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("hh", 8));
OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("mc", 8));
OMINOUS_BANNER_PATTERN.add(getJavaPatternTag("bo", 15));
OMINOUS_BANNER_PATTERN = List.of(
new BannerPatternLayer("mr", 9),
new BannerPatternLayer("bs", 8),
new BannerPatternLayer("cs", 7),
new BannerPatternLayer("bo", 8),
new BannerPatternLayer("ms", 15),
new BannerPatternLayer("hh", 8),
new BannerPatternLayer("mc", 8),
new BannerPatternLayer("bo", 15)
);
}

/**
Expand Down Expand Up @@ -102,7 +103,7 @@ private static NbtMap getBedrockBannerPattern(CompoundTag pattern) {
* @return The Java edition format pattern nbt
*/
public static CompoundTag getJavaBannerPattern(NbtMap pattern) {
return getJavaPatternTag(pattern.getString("Pattern"), 15 - pattern.getInt("Color"));
return new BannerPatternLayer(pattern.getString("Pattern"), 15 - pattern.getInt("Color"));
}

/**
Expand All @@ -122,14 +123,14 @@ public BannerItem(String javaIdentifier, Builder builder) {
}

@Override
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) {
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder);

CompoundTag blockEntityTag = tag.remove("BlockEntityTag");
if (blockEntityTag != null && blockEntityTag.get("Patterns") instanceof ListTag patterns) {
List<BannerPatternLayer> patterns = components.get(DataComponentType.BANNER_PATTERNS);
if (patterns != null) {
if (patterns.equals(OMINOUS_BANNER_PATTERN)) {
// Remove the current patterns and set the ominous banner type
tag.put(new IntTag("Type", 1));
builder.putInt("Type", 1);
} else {
invertBannerColors(patterns);
tag.put(patterns);
Expand Down
16 changes: 3 additions & 13 deletions core/src/main/java/org/geysermc/geyser/item/type/ChestItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,18 @@

import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;

@Deprecated
public class ChestItem extends BlockItem {

public ChestItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}

@Override
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) {
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder);

// Strip the BlockEntityTag from the chests contents
// sent to the client. The client does not parse this
// or use it for anything, as this tag is fully
// server-side, so we remove it to reduce bandwidth and
// solve potential issues with very large tags.

// There was a problem in the past where this would strip
// NBT data in creative mode, however with the new server
// authoritative inventories, this is no longer a concern.
tag.remove("BlockEntityTag");
}
}
34 changes: 16 additions & 18 deletions core/src/main/java/org/geysermc/geyser/item/type/CompassItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,16 @@
package org.geysermc.geyser.item.type;

import com.github.steveice10.mc.protocol.data.game.item.ItemStack;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
import com.github.steveice10.opennbt.tag.builtin.ByteTag;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.github.steveice10.mc.protocol.data.game.item.component.LodestoneTracker;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;

public class CompassItem extends Item {
public CompassItem(String javaIdentifier, Builder builder) {
Expand All @@ -45,36 +44,35 @@ public CompassItem(String javaIdentifier, Builder builder) {

@Override
public ItemData.Builder translateToBedrock(ItemStack itemStack, ItemMapping mapping, ItemMappings mappings) {
if (isLodestoneCompass(itemStack.getNbt())) {
if (isLodestoneCompass(itemStack.getDataComponents())) {
return super.translateToBedrock(itemStack, mappings.getLodestoneCompass(), mappings);
}
return super.translateToBedrock(itemStack, mapping, mappings);
}

@Override
public ItemMapping toBedrockDefinition(CompoundTag nbt, ItemMappings mappings) {
if (isLodestoneCompass(nbt)) {
public ItemMapping toBedrockDefinition(DataComponents components, ItemMappings mappings) {
if (isLodestoneCompass(components)) {
return mappings.getLodestoneCompass();
}
return super.toBedrockDefinition(nbt, mappings);
return super.toBedrockDefinition(components, mappings);
}

@Override
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) {
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder);

Tag lodestoneTag = tag.get("LodestoneTracked");
if (lodestoneTag instanceof ByteTag) {
int trackId = session.getLodestoneCache().store(tag);
LodestoneTracker tracker = components.get(DataComponentType.LODESTONE_TRACKER);
if (tracker != null) {
int trackId = session.getLodestoneCache().store(tracker);
// Set the bedrock tracking id - will return 0 if invalid
tag.put(new IntTag("trackingHandle", trackId));
builder.putInt("trackingHandle", trackId);
}
}

private boolean isLodestoneCompass(CompoundTag nbt) {
if (nbt != null) {
Tag lodestoneTag = nbt.get("LodestoneTracked");
return lodestoneTag instanceof ByteTag;
private boolean isLodestoneCompass(@Nullable DataComponents components) {
if (components != null) {
return components.getDataComponents().containsKey(DataComponentType.LODESTONE_TRACKER);
}
return false;
}
Expand Down
35 changes: 16 additions & 19 deletions core/src/main/java/org/geysermc/geyser/item/type/CrossbowItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,44 +26,41 @@
package org.geysermc.geyser.item.type;

import com.github.steveice10.mc.protocol.data.game.item.ItemStack;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType;
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
import com.github.steveice10.opennbt.tag.builtin.*;
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.StringTag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.geyser.translator.item.ItemTranslator;

import java.util.List;

public class CrossbowItem extends Item {
public CrossbowItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}

@Override
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull NbtMapBuilder builder) {
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
super.translateComponentsToBedrock(session, components, builder);

ListTag chargedProjectiles = tag.get("ChargedProjectiles");
if (chargedProjectiles != null) {
if (!chargedProjectiles.getValue().isEmpty()) {
CompoundTag javaProjectileAsNbt = (CompoundTag) chargedProjectiles.getValue().get(0);

ItemMapping projectileMapping = session.getItemMappings().getMapping((String) javaProjectileAsNbt.get("id").getValue());
if (projectileMapping == null) return;
@Nullable CompoundTag projectileTag = javaProjectileAsNbt.get("tag");
ItemStack itemStack = new ItemStack(projectileMapping.getJavaItem().javaId(), (byte) javaProjectileAsNbt.get("Count").getValue(), projectileTag);
ItemData itemData = ItemTranslator.translateToBedrock(session, itemStack);
List<ItemStack> chargedProjectiles = components.get(DataComponentType.CHARGED_PROJECTILES);
if (chargedProjectiles != null && !chargedProjectiles.isEmpty()) {
ItemStack javaProjectile = chargedProjectiles.get(0);

CompoundTag newProjectile = new CompoundTag("chargedItem");
newProjectile.put(new ByteTag("Count", (byte) itemData.getCount()));
newProjectile.put(new StringTag("Name", projectileMapping.getBedrockIdentifier()));
ItemMapping projectileMapping = session.getItemMappings().getMapping(javaProjectile.getId());
ItemData itemData = ItemTranslator.translateToBedrock(session, javaProjectile);

newProjectile.put(new ShortTag("Damage", (short) itemData.getDamage()));
NbtMapBuilder newProjectile = BedrockItemBuilder.createItemNbt(projectileMapping, itemData.getCount(), itemData.getDamage());

tag.put(newProjectile);
}
builder.putCompound("chargedItem", newProjectile.build());
}
}

Expand Down
Loading

0 comments on commit 78edbac

Please sign in to comment.