Skip to content

Commit bf93cc3

Browse files
authored
Change cakes, armor stand stack size to match JE, make fireworks rocket boosting server controlled. (#5673)
* Change certain bedrock item stack size to match JE. * Make fireworks rocket boosting server controlled. * Added support for hidden tooltip and translation strings. * Requested changes. * Don't mess with the item mappings. * yipeeeeee. * Removed unused imports. * oops.
1 parent ba8eabb commit bf93cc3

File tree

4 files changed

+163
-5
lines changed

4 files changed

+163
-5
lines changed

core/src/main/java/org/geysermc/geyser/item/type/FireworkRocketItem.java

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
package org.geysermc.geyser.item.type;
2727

28+
import com.google.gson.JsonArray;
29+
import com.google.gson.JsonObject;
2830
import it.unimi.dsi.fastutil.ints.IntArrays;
2931
import org.checkerframework.checker.nullness.qual.NonNull;
3032
import org.cloudburstmc.nbt.NbtList;
@@ -56,6 +58,7 @@ public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNul
5658
if (fireworks == null) {
5759
return;
5860
}
61+
// We still need to translate the explosion so this is still correct, and can be reverse translate in translateNbtToJava.
5962
NbtMapBuilder fireworksNbt = NbtMap.builder();
6063
fireworksNbt.putByte("Flight", (byte) fireworks.getFlightDuration());
6164

@@ -71,6 +74,52 @@ public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNul
7174
fireworksNbt.put("Explosions", NbtList.EMPTY);
7275
}
7376
builder.putCompound("Fireworks", fireworksNbt.build());
77+
78+
// If the tooltip is hidden, don't add any lore.
79+
if (!tooltip.showInTooltip(DataComponentTypes.FIREWORKS)) {
80+
return;
81+
}
82+
83+
// Then we translate everything into lore since the explosion tag and everything is not visible anymore due to this being a data driven item.
84+
List<String> lore = builder.getOrCreateLore();
85+
lore.add(withTranslation("§r", "item.fireworks.flight", " " + fireworks.getFlightDuration()));
86+
87+
for (Fireworks.FireworkExplosion explosion : explosions) {
88+
lore.add(withTranslation("§r ", "item.fireworksCharge.type." + explosion.getShapeId()));
89+
90+
final List<String> colors = new ArrayList<>();
91+
colors.add("§r ");
92+
for (int color : explosion.getColors()) {
93+
FireworkColor fireworkColor = FireworkColor.values()[FireworkColor.fromJavaRGB(color)];
94+
colors.add("item.fireworksCharge." + fireworkColor.getName());
95+
colors.add(" ");
96+
}
97+
98+
if (explosion.getColors().length != 0) {
99+
lore.add(withTranslation(colors.toArray(new String[0])));
100+
}
101+
102+
colors.clear();
103+
colors.add("§r ");
104+
colors.add("item.fireworksCharge.fadeTo");
105+
colors.add(" ");
106+
for (int color : explosion.getFadeColors()) {
107+
FireworkColor fireworkColor = FireworkColor.values()[FireworkColor.fromJavaRGB(color)];
108+
colors.add("item.fireworksCharge." + fireworkColor.getName());
109+
colors.add(" ");
110+
}
111+
if (explosion.getFadeColors().length != 0) {
112+
lore.add(withTranslation(colors.toArray(new String[0])));
113+
}
114+
115+
if (explosion.isHasTrail()) {
116+
lore.add(withTranslation("§r ", "item.fireworksCharge.trail"));
117+
}
118+
119+
if (explosion.isHasTwinkle()) {
120+
lore.add(withTranslation("§r ", "item.fireworksCharge.flicker"));
121+
}
122+
}
74123
}
75124

76125
@Override
@@ -79,6 +128,11 @@ public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap b
79128

80129
NbtMap fireworksTag = bedrockTag.getCompound("Fireworks");
81130
if (!fireworksTag.isEmpty()) {
131+
int flightDuration = 1;
132+
if (fireworksTag.containsKey("Flight")) {
133+
flightDuration = fireworksTag.getByte("Flight");
134+
}
135+
82136
List<NbtMap> explosions = fireworksTag.getList("Explosions", NbtType.COMPOUND);
83137
if (!explosions.isEmpty()) {
84138
List<Fireworks.FireworkExplosion> javaExplosions = new ArrayList<>();
@@ -88,7 +142,9 @@ public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap b
88142
javaExplosions.add(javaExplosion);
89143
}
90144
}
91-
components.put(DataComponentTypes.FIREWORKS, new Fireworks(1, javaExplosions));
145+
components.put(DataComponentTypes.FIREWORKS, new Fireworks(flightDuration, javaExplosions));
146+
} else {
147+
components.put(DataComponentTypes.FIREWORKS, new Fireworks(flightDuration, List.of()));
92148
}
93149
}
94150
}
@@ -142,4 +198,18 @@ static Fireworks.FireworkExplosion translateExplosionToJava(NbtMap explosion) {
142198
return null;
143199
}
144200
}
201+
202+
public static String withTranslation(String... strings) {
203+
final JsonObject object = new JsonObject();
204+
final JsonArray array = new JsonArray();
205+
206+
for (String s : strings) {
207+
final JsonObject object1 = new JsonObject();
208+
object1.addProperty("translate", s);
209+
array.add(object1);
210+
}
211+
212+
object.add("rawtext", array);
213+
return object.toString();
214+
}
145215
}

core/src/main/java/org/geysermc/geyser/item/type/Item.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,11 @@ public ItemMapping toBedrockDefinition(DataComponents components, ItemMappings m
174174
/**
175175
* Takes components from Java Edition and map them into Bedrock.
176176
*/
177-
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull TooltipOptions tooltip, @NonNull BedrockItemBuilder builder) {
177+
public void translateComponentsToBedrock(GeyserSession session, @NonNull DataComponents components, @NonNull TooltipOptions tooltip, @NonNull BedrockItemBuilder builder) {
178+
if (session == null) {
179+
return;
180+
}
181+
178182
List<Component> loreComponents = components.get(DataComponentTypes.LORE);
179183
if (loreComponents != null && tooltip.showInTooltip(DataComponentTypes.LORE)) {
180184
List<String> lore = builder.getOrCreateLore();
@@ -235,7 +239,7 @@ public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNul
235239
* </ul>
236240
* Therefore, if translation cannot be achieved for a certain item, it is not necessarily bad.
237241
*/
238-
public void translateNbtToJava(@NonNull GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) {
242+
public void translateNbtToJava(GeyserSession session, @NonNull NbtMap bedrockTag, @NonNull DataComponents components, ItemMapping mapping) {
239243
// TODO see if any items from the creative menu need this
240244
// CompoundTag displayTag = tag.get("display");
241245
// if (displayTag != null) {

core/src/main/java/org/geysermc/geyser/level/FireworkColor.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525

2626
package org.geysermc.geyser.level;
2727

28+
import lombok.Getter;
2829
import net.kyori.adventure.text.format.TextColor;
2930
import net.kyori.adventure.util.HSVLike;
3031
import org.checkerframework.checker.nullness.qual.NonNull;
3132

33+
import java.util.Locale;
34+
3235
public enum FireworkColor {
3336
BLACK(1973019),
3437
RED(11743532),
@@ -37,12 +40,12 @@ public enum FireworkColor {
3740
BLUE(2437522),
3841
PURPLE(8073150),
3942
CYAN(2651799),
40-
LIGHT_GRAY(11250603),
43+
LIGHT_GRAY(11250603, "silver"),
4144
GRAY(4408131),
4245
PINK(14188952),
4346
LIME(4312372),
4447
YELLOW(14602026),
45-
LIGHT_BLUE(6719955),
48+
LIGHT_BLUE(6719955, "lightBlue"),
4649
MAGENTA(12801229),
4750
ORANGE(15435844),
4851
WHITE(15790320);
@@ -51,8 +54,17 @@ public enum FireworkColor {
5154

5255
private final TextColor color;
5356

57+
@Getter
58+
private final String name;
59+
60+
FireworkColor(int rgbValue, String name) {
61+
this.color = TextColor.color(rgbValue);
62+
this.name = name;
63+
}
64+
5465
FireworkColor(int rgbValue) {
5566
this.color = TextColor.color(rgbValue);
67+
this.name = this.name().toLowerCase(Locale.ROOT);
5668
}
5769

5870
private static HSVLike toHSV(int rgbValue) {

core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import org.geysermc.geyser.inventory.item.StoredItemMappings;
7474
import org.geysermc.geyser.item.GeyserCustomMappingData;
7575
import org.geysermc.geyser.item.Items;
76+
import org.geysermc.geyser.item.TooltipOptions;
7677
import org.geysermc.geyser.item.custom.GeyserCustomItemDefinition;
7778
import org.geysermc.geyser.item.custom.impl.predicates.GeyserRangeDispatchPredicate;
7879
import org.geysermc.geyser.item.exception.InvalidItemComponentsException;
@@ -88,6 +89,8 @@
8889
import org.geysermc.geyser.registry.type.ItemMappings;
8990
import org.geysermc.geyser.registry.type.NonVanillaItemRegistration;
9091
import org.geysermc.geyser.registry.type.PaletteItem;
92+
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
93+
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
9194
import org.geysermc.geyser.util.MinecraftKey;
9295
import org.geysermc.geyser.util.JsonUtils;
9396

@@ -223,6 +226,20 @@ public static void populate() {
223226
}
224227

225228
ItemDefinition definition = new SimpleItemDefinition(entry.getName().intern(), id, ItemVersion.from(entry.getVersion()), entry.isComponentBased(), components);
229+
230+
// Some item on Bedrock Edition have a different stack size, so we're changing that through the component.
231+
// This resolve https://github.com/GeyserMC/Geyser/issues/5612 and https://github.com/GeyserMC/Geyser/issues/4905
232+
if (definition.getIdentifier().equals("minecraft:cake")) {
233+
definition = new SimpleItemDefinition(entry.getName().intern(), id, ItemVersion.from(entry.getVersion()), true, fromItemDefinitionToDataDriven(definition, 1, null, null));
234+
} else if (definition.getIdentifier().equals("minecraft:armor_stand")) {
235+
// You have to change the item version to data driven for armor stand else this won't work.
236+
definition = new SimpleItemDefinition(entry.getName().intern(), id, ItemVersion.DATA_DRIVEN, true, fromItemDefinitionToDataDriven(definition, 16, "armor_stand", "item.armor_stand.name"));
237+
} else if (definition.getIdentifier().equals("minecraft:firework_rocket")) {
238+
// For fireworks rocket, we purposely make this item data driven so now bedrock won't do client-sided boosting
239+
// and now we can control fireworks boost ourselves! This resolve https://github.com/GeyserMC/Geyser/issues/5409
240+
definition = new SimpleItemDefinition(entry.getName().intern(), id, ItemVersion.DATA_DRIVEN, true, fromItemDefinitionToDataDriven(definition, 64, "fireworks", "item.fireworks.name"));
241+
}
242+
226243
definitions.put(entry.getName(), definition);
227244
registry.put(definition.getRuntimeId(), definition);
228245
}
@@ -722,6 +739,32 @@ public static void populate() {
722739
}
723740
}
724741

742+
// Since the fireworks tag now won't show up due to this is being a data driven item, we have to translate it to lore ourselves
743+
for (int j = 0; j < creativeItems.size(); j++) {
744+
CreativeItemData itemData = creativeItems.get(j);
745+
if (!itemData.getItem().getDefinition().getIdentifier().equals("minecraft:firework_rocket")) {
746+
continue;
747+
}
748+
749+
NbtMap tag = null;
750+
if (itemData.getItem().getTag() != null) {
751+
final DataComponents components = new DataComponents(new HashMap<>());
752+
Items.FIREWORK_ROCKET.translateNbtToJava(null, itemData.getItem().getTag(), components, null);
753+
final BedrockItemBuilder builder = new BedrockItemBuilder();
754+
Items.FIREWORK_ROCKET.translateComponentsToBedrock(null, components, TooltipOptions.ALL_SHOWN, builder);
755+
756+
tag = builder.build();
757+
}
758+
759+
creativeItems.set(j, new CreativeItemData(ItemData.builder()
760+
.usingNetId(true)
761+
.netId(itemData.getItem().getNetId())
762+
.definition(itemData.getItem().getDefinition())
763+
.tag(tag)
764+
.count(itemData.getItem().getCount())
765+
.build(), itemData.getNetId(), itemData.getGroupId()));
766+
}
767+
725768
ItemMappings itemMappings = ItemMappings.builder()
726769
.items(mappings.toArray(new ItemMapping[0]))
727770
.zeroBlockDefinitionRuntimeId(mappings.stream()
@@ -784,6 +827,35 @@ private static NbtMap registerFurnaceMinecart(int nextFreeBedrockId) {
784827
builder.putCompound("components", componentBuilder.build());
785828
return builder.build();
786829
}
830+
831+
private static NbtMap fromItemDefinitionToDataDriven(ItemDefinition definition, int maxStackSize, String texture, String displayName) {
832+
NbtMapBuilder builder = NbtMap.builder();
833+
builder.putString("name", definition.getIdentifier()).putInt("id", definition.getRuntimeId());
834+
835+
NbtMapBuilder itemProperties = NbtMap.builder();
836+
837+
NbtMapBuilder componentBuilder = NbtMap.builder();
838+
839+
if (texture != null) {
840+
NbtMap iconMap = NbtMap.builder()
841+
.putCompound("textures", NbtMap.builder()
842+
.putString("default", texture)
843+
.build())
844+
.build();
845+
itemProperties.putCompound("minecraft:icon", iconMap);
846+
}
847+
848+
if (displayName != null) {
849+
componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", displayName).build());
850+
}
851+
852+
itemProperties.putBoolean("allow_off_hand", true);
853+
itemProperties.putInt("max_stack_size", maxStackSize);
854+
855+
componentBuilder.putCompound("item_properties", itemProperties.build());
856+
builder.putCompound("components", componentBuilder.build());
857+
return builder.build();
858+
}
787859

788860
public static int getCreativeIndex(String creativeGroup, CreativeItemCategory creativeItemCategory, Map<String, Integer> groupIndexes, Map<CreativeItemCategory, Integer> fallBacks, List<CreativeItemGroup> creativeItemGroups) {
789861
if (fallBacks.isEmpty()) {

0 commit comments

Comments
 (0)