Workaround for goat horns on the client side

This commit is contained in:
Camotoy 2024-09-14 18:30:25 -04:00
parent 34fda8a743
commit a5e45ad7ed
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
3 changed files with 54 additions and 0 deletions

View file

@ -34,6 +34,7 @@ import lombok.Setter;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.scoreboard.Scoreboard;
import org.geysermc.geyser.scoreboard.ScoreboardUpdater.ScoreboardSession;
import org.geysermc.geyser.session.GeyserSession;
@ -70,6 +71,8 @@ public final class WorldCache {
@Setter
private boolean editingSignOnFront;
private final Object2IntMap<Item> activeCooldowns = new Object2IntOpenHashMap<>(2);
public WorldCache(GeyserSession session) {
this.session = session;
this.scoreboard = new Scoreboard(session);
@ -201,4 +204,32 @@ public final class WorldCache {
public String removeActiveRecord(Vector3i pos) {
return this.activeRecords.remove(pos);
}
public void setCooldown(Item item, int ticks) {
if (ticks == 0) {
// As of Java 1.21
this.activeCooldowns.removeInt(item);
return;
}
this.activeCooldowns.put(item, session.getTicks() + ticks);
}
public boolean hasCooldown(Item item) {
return this.activeCooldowns.containsKey(item);
}
public void tick() {
// Implementation note: technically we could empty the field during hasCooldown checks,
// but we don't want the cooldown field to balloon in size from overuse.
if (!this.activeCooldowns.isEmpty()) {
int ticks = session.getTicks();
Iterator<Object2IntMap.Entry<Item>> it = Object2IntMaps.fastIterator(this.activeCooldowns);
while (it.hasNext()) {
Object2IntMap.Entry<Item> entry = it.next();
if (entry.getIntValue() <= ticks) {
it.remove();
}
}
}
}
}

View file

@ -31,6 +31,7 @@ import org.cloudburstmc.math.vector.Vector3d;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
@ -42,6 +43,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.LegacySetIte
import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventoryTransactionPacket;
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Entity;
@ -75,12 +77,15 @@ import org.geysermc.geyser.util.CooldownUtils;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InventoryUtils;
import org.geysermc.mcprotocollib.protocol.data.game.Holder;
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractAction;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.Instrument;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
@ -373,6 +378,22 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
break;
} else if (packet.getItemInHand().getDefinition() == session.getItemMappings().getStoredItems().writtenBook().getBedrockDefinition()) {
session.setCurrentBook(packet.getItemInHand());
} else if (session.getPlayerInventory().getItemInHand().asItem() == Items.GOAT_HORN) {
// Temporary workaround while we don't have full item/block use tracking.
if (!session.getWorldCache().hasCooldown(Items.GOAT_HORN)) {
Holder<Instrument> instrument = session.getPlayerInventory()
.getItemInHand()
.getComponent(DataComponentType.INSTRUMENT);
if (instrument != null && instrument.isId()) {
// BDS uses a LevelSoundEvent2Packet, but that doesn't work here... (as of 1.21.20)
LevelSoundEventPacket soundPacket = new LevelSoundEventPacket();
soundPacket.setSound(SoundEvent.valueOf("GOAT_CALL_" + instrument.id()));
soundPacket.setPosition(session.getPlayerEntity().getPosition());
soundPacket.setIdentifier("minecraft:player");
soundPacket.setExtraData(-1);
session.sendUpstreamPacket(soundPacket);
}
}
}
}

View file

@ -57,5 +57,7 @@ public class JavaCooldownTranslator extends PacketTranslator<ClientboundCooldown
bedrockPacket.setCooldownDuration(packet.getCooldownTicks());
session.sendUpstreamPacket(bedrockPacket);
}
session.getWorldCache().setCooldown(item, packet.getCooldownTicks());
}
}