mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-27 15:00:28 +01:00
Use integrated world managers for decorated pot animation
This commit is contained in:
parent
6884a0f7db
commit
2c47330509
4 changed files with 75 additions and 0 deletions
|
@ -30,6 +30,7 @@ import net.minecraft.SharedConstants;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.core.component.DataComponents;
|
import net.minecraft.core.component.DataComponents;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
@ -39,10 +40,12 @@ import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BannerBlockEntity;
|
import net.minecraft.world.level.block.entity.BannerBlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BannerPatternLayers;
|
import net.minecraft.world.level.block.entity.BannerPatternLayers;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import org.geysermc.geyser.level.GeyserWorldManager;
|
import org.geysermc.geyser.level.GeyserWorldManager;
|
||||||
import org.geysermc.geyser.network.GameProtocol;
|
import org.geysermc.geyser.network.GameProtocol;
|
||||||
import org.geysermc.geyser.platform.mod.GeyserModBootstrap;
|
import org.geysermc.geyser.platform.mod.GeyserModBootstrap;
|
||||||
|
@ -56,6 +59,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class GeyserModWorldManager extends GeyserWorldManager {
|
public class GeyserModWorldManager extends GeyserWorldManager {
|
||||||
|
|
||||||
|
@ -161,6 +165,27 @@ public class GeyserModWorldManager extends GeyserWorldManager {
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer<List<String>> apply) {
|
||||||
|
server.execute(() -> {
|
||||||
|
ServerPlayer player = getPlayer(session);
|
||||||
|
if (player == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPos blockPos = new BlockPos(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
// Don't create a new block entity if invalid
|
||||||
|
//noinspection resource - level() is just a getter
|
||||||
|
BlockEntity blockEntity = player.level().getChunkAt(blockPos).getBlockEntity(blockPos);
|
||||||
|
if (blockEntity instanceof DecoratedPotBlockEntity pot) {
|
||||||
|
List<String> sherds = pot.getDecorations().ordered()
|
||||||
|
.stream().map(item -> BuiltInRegistries.ITEM.getKey(item).toString())
|
||||||
|
.toList();
|
||||||
|
apply.accept(sherds);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private ServerPlayer getPlayer(GeyserSession session) {
|
private ServerPlayer getPlayer(GeyserSession session) {
|
||||||
return server.getPlayerList().getPlayer(session.getPlayerEntity().getUuid());
|
return server.getPlayerList().getPlayer(session.getPlayerEntity().getUuid());
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,13 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.DecoratedPot;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
|
import org.geysermc.erosion.bukkit.BukkitUtils;
|
||||||
import org.geysermc.erosion.bukkit.PickBlockUtils;
|
import org.geysermc.erosion.bukkit.PickBlockUtils;
|
||||||
import org.geysermc.erosion.bukkit.SchedulerUtils;
|
import org.geysermc.erosion.bukkit.SchedulerUtils;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
@ -43,8 +46,10 @@ import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base world manager to use when there is no supported NMS revision
|
* The base world manager to use when there is no supported NMS revision
|
||||||
|
@ -146,6 +151,21 @@ public class GeyserSpigotWorldManager extends WorldManager {
|
||||||
return future.thenApply(RAW_TRANSFORMER);
|
return future.thenApply(RAW_TRANSFORMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer<List<String>> apply) {
|
||||||
|
Player bukkitPlayer;
|
||||||
|
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Block block = bukkitPlayer.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
SchedulerUtils.runTask(this.plugin, () -> {
|
||||||
|
var state = BukkitUtils.getBlockState(block);
|
||||||
|
if (!(state instanceof DecoratedPot pot)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
apply.accept(pot.getShards().stream().map(material -> material.getKey().toString()).toList());
|
||||||
|
}, block);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This should be set to true if we are post-1.13 but before the latest version, and we should convert the old block state id
|
* This should be set to true if we are post-1.13 but before the latest version, and we should convert the old block state id
|
||||||
* to the current one.
|
* to the current one.
|
||||||
|
|
|
@ -43,9 +43,11 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemCodecHel
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty;
|
import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -209,6 +211,13 @@ public abstract class WorldManager {
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves decorated pot sherds from the server. Used to ensure the data is not erased on animation sent
|
||||||
|
* through the BlockEntityDataPacket.
|
||||||
|
*/
|
||||||
|
public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer<List<String>> apply) {
|
||||||
|
}
|
||||||
|
|
||||||
protected static final Function<Int2ObjectMap<byte[]>, DataComponents> RAW_TRANSFORMER = map -> {
|
protected static final Function<Int2ObjectMap<byte[]>, DataComponents> RAW_TRANSFORMER = map -> {
|
||||||
try {
|
try {
|
||||||
Map<DataComponentType<?>, DataComponent<?, ?>> components = new HashMap<>();
|
Map<DataComponentType<?>, DataComponent<?, ?>> components = new HashMap<>();
|
||||||
|
|
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.protocol.java.level;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
||||||
import org.cloudburstmc.math.vector.Vector3i;
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||||
|
import org.cloudburstmc.nbt.NbtType;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.BlockEventPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.BlockEventPacket;
|
||||||
import org.geysermc.geyser.api.util.PlatformType;
|
import org.geysermc.geyser.api.util.PlatformType;
|
||||||
|
@ -126,6 +127,26 @@ public class JavaBlockEventTranslator extends PacketTranslator<ClientboundBlockE
|
||||||
|
|
||||||
blockEntityPacket.setData(builder.build());
|
blockEntityPacket.setData(builder.build());
|
||||||
session.sendUpstreamPacket(blockEntityPacket);
|
session.sendUpstreamPacket(blockEntityPacket);
|
||||||
|
} else if (value instanceof DecoratedPotValue potValue) {
|
||||||
|
// Decorated pots - wobble wobble
|
||||||
|
// We need to send the sherd data with the client, but we don't really care about latency here so we
|
||||||
|
// can safely get this from the server
|
||||||
|
session.getGeyser().getWorldManager().getDecoratedPotData(session, position, sherds -> {
|
||||||
|
BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket();
|
||||||
|
blockEntityPacket.setBlockPosition(position);
|
||||||
|
|
||||||
|
NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("DecoratedPot", position);
|
||||||
|
builder.putList("sherds", NbtType.STRING, sherds);
|
||||||
|
builder.putByte("animation", switch (potValue.getWobbleStyle()) {
|
||||||
|
case POSITIVE -> (byte) 2;
|
||||||
|
case NEGATIVE -> (byte) 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
blockEntityPacket.setData(builder.build());
|
||||||
|
session.sendUpstreamPacket(blockEntityPacket);
|
||||||
|
});
|
||||||
|
} else if (session.getGeyser().getLogger().isDebug()) {
|
||||||
|
session.getGeyser().getLogger().debug("Unhandled block event packet: " + packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue