Use server data to pick block on banners

This commit is contained in:
Camotoy 2022-12-17 21:05:41 -05:00
parent 47fd148b7e
commit ad4424d2b6
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
7 changed files with 254 additions and 21 deletions

View file

@ -27,12 +27,15 @@ package org.geysermc.geyser.level;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap;
import org.geysermc.geyser.session.GeyserSession;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
/**
* Class that manages or retrieves various information
@ -166,4 +169,14 @@ public abstract class WorldManager {
public String[] getBiomeIdentifiers(boolean withTags) {
return null;
}
/**
* Used for pick block, so we don't need to cache more data than necessary.
*
* @return expected NBT for this item.
*/
@Nonnull
public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) {
return CompletableFuture.completedFuture(null);
}
}

View file

@ -1073,6 +1073,17 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
closed = true;
}
/**
* Moves task to the session event loop if already not in it. Otherwise, the task is automatically ran.
*/
public void ensureInEventLoop(Runnable runnable) {
if (eventLoop.inEventLoop()) {
runnable.run();
return;
}
executeInEventLoop(runnable);
}
/**
* Executes a task and prints a stack trace if an error occurs.
*/

View file

@ -56,17 +56,17 @@ public class BannerTranslator extends NbtItemStackTranslator {
static {
OMINOUS_BANNER_PATTERN = new ListTag("Patterns");
// Construct what an ominous banner is supposed to look like
OMINOUS_BANNER_PATTERN.add(getPatternTag("mr", 9));
OMINOUS_BANNER_PATTERN.add(getPatternTag("bs", 8));
OMINOUS_BANNER_PATTERN.add(getPatternTag("cs", 7));
OMINOUS_BANNER_PATTERN.add(getPatternTag("bo", 8));
OMINOUS_BANNER_PATTERN.add(getPatternTag("ms", 15));
OMINOUS_BANNER_PATTERN.add(getPatternTag("hh", 8));
OMINOUS_BANNER_PATTERN.add(getPatternTag("mc", 8));
OMINOUS_BANNER_PATTERN.add(getPatternTag("bo", 15));
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));
}
private static CompoundTag getPatternTag(String pattern, int color) {
public static CompoundTag getJavaPatternTag(String pattern, int color) {
StringTag patternType = new StringTag("Pattern", pattern);
IntTag colorTag = new IntTag("Color", color);
CompoundTag tag = new CompoundTag("");
@ -117,11 +117,7 @@ public class BannerTranslator extends NbtItemStackTranslator {
* @return The Java edition format pattern nbt
*/
public static CompoundTag getJavaBannerPattern(NbtMap pattern) {
Map<String, Tag> tags = new HashMap<>();
tags.put("Color", new IntTag("Color", 15 - pattern.getInt("Color")));
tags.put("Pattern", new StringTag("Pattern", pattern.getString("Pattern")));
return new CompoundTag("", tags);
return BannerTranslator.getJavaPatternTag(pattern.getString("Pattern"), 15 - pattern.getInt("Color"));
}
/**

View file

@ -25,12 +25,18 @@
package org.geysermc.geyser.translator.protocol.bedrock;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
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 com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.packet.BlockPickRequestPacket;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.ItemFrameEntity;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
@ -61,6 +67,41 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator<BlockPic
return;
}
InventoryUtils.findOrCreateItem(session, BlockRegistries.JAVA_BLOCKS.get(blockToPick).getPickItem());
BlockMapping blockMapping = BlockRegistries.JAVA_BLOCKS.getOrDefault(blockToPick, BlockMapping.AIR);
boolean addNbtData = packet.isAddUserData() && blockMapping.isBlockEntity(); // Holding down CTRL
if (BlockStateValues.getBannerColor(blockToPick) != -1 || addNbtData) {
session.getGeyser().getWorldManager().getPickItemNbt(session, vector.getX(), vector.getY(), vector.getZ(), addNbtData)
.whenComplete((tag, ex) -> {
if (tag == null) {
pickItem(session, blockMapping);
return;
}
session.ensureInEventLoop(() -> {
if (addNbtData) {
ListTag lore = new ListTag("Lore");
lore.add(new StringTag("", "\"(+NBT)\""));
CompoundTag display = tag.get("display");
if (display == null) {
display = new CompoundTag("display");
tag.put(display);
}
display.put(lore);
}
// I don't really like this... I'd rather get an ID from the block mapping I think
ItemMapping mapping = session.getItemMappings().getMapping(blockMapping.getPickItem());
ItemStack itemStack = new ItemStack(mapping.getJavaId(), 1, tag);
InventoryUtils.findOrCreateItem(session, itemStack);
});
});
return;
}
pickItem(session, blockMapping);
}
private void pickItem(GeyserSession session, BlockMapping blockToPick) {
InventoryUtils.findOrCreateItem(session, blockToPick.getPickItem());
}
}

View file

@ -25,7 +25,6 @@
package org.geysermc.geyser.translator.protocol.bedrock;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.nukkitx.protocol.bedrock.packet.EntityPickRequestPacket;
import org.geysermc.geyser.entity.type.BoatEntity;
import org.geysermc.geyser.entity.type.Entity;
@ -45,7 +44,10 @@ public class BedrockEntityPickRequestTranslator extends PacketTranslator<EntityP
@Override
public void translate(GeyserSession session, EntityPickRequestPacket packet) {
if (session.getGameMode() != GameMode.CREATIVE) return; // Apparently Java behavior
if (!session.isInstabuild()) {
// As of Java Edition 1.19.3
return;
}
Entity entity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId());
if (entity == null) return;