Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-20 15:00:11 +01:00
Merge branch 'master' into new-mcpl
Dieser Commit ist enthalten in:
Commit
c79aea4e4e
@ -25,8 +25,7 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.item.enchantment;
|
package org.geysermc.geyser.item.enchantment;
|
||||||
|
|
||||||
import java.util.List;
|
import it.unimi.dsi.fastutil.ints.IntArrays;
|
||||||
import java.util.function.Function;
|
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.cloudburstmc.nbt.NbtMap;
|
import org.cloudburstmc.nbt.NbtMap;
|
||||||
@ -35,11 +34,14 @@ import org.geysermc.geyser.item.Items;
|
|||||||
import org.geysermc.geyser.registry.Registries;
|
import org.geysermc.geyser.registry.Registries;
|
||||||
import org.geysermc.geyser.session.cache.registry.RegistryEntryContext;
|
import org.geysermc.geyser.session.cache.registry.RegistryEntryContext;
|
||||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||||
|
import org.geysermc.geyser.util.MinecraftKey;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
|
import java.util.function.ToIntFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param description only populated if {@link #bedrockEnchantment()} is not null.
|
* @param description only populated if {@link #bedrockEnchantment()} is not null.
|
||||||
@ -86,21 +88,21 @@ public record Enchantment(String identifier,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO holder set util?
|
// TODO holder set util?
|
||||||
private static HolderSet readHolderSet(@Nullable Object holderSet, Function<Key, Integer> keyIdMapping) {
|
private static HolderSet readHolderSet(@Nullable Object holderSet, ToIntFunction<Key> keyIdMapping) {
|
||||||
if (holderSet == null) {
|
if (holderSet == null) {
|
||||||
return new HolderSet(new int[]{});
|
return new HolderSet(IntArrays.EMPTY_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (holderSet instanceof String stringTag) {
|
if (holderSet instanceof String stringTag) {
|
||||||
// Tag
|
// Tag
|
||||||
if (stringTag.startsWith("#")) {
|
if (stringTag.startsWith("#")) {
|
||||||
return new HolderSet(Key.key(stringTag.substring(1))); // Remove '#' at beginning that indicates tag
|
return new HolderSet(MinecraftKey.key(stringTag.substring(1))); // Remove '#' at beginning that indicates tag
|
||||||
} else {
|
} else {
|
||||||
return new HolderSet(new int[]{keyIdMapping.apply(Key.key(stringTag))});
|
return new HolderSet(new int[]{keyIdMapping.applyAsInt(MinecraftKey.key(stringTag))});
|
||||||
}
|
}
|
||||||
} else if (holderSet instanceof List<?> list) {
|
} else if (holderSet instanceof List<?> list) {
|
||||||
// Assume the list is a list of strings
|
// Assume the list is a list of strings
|
||||||
return new HolderSet(list.stream().map(o -> (String) o).map(Key::key).map(keyIdMapping).mapToInt(Integer::intValue).toArray());
|
return new HolderSet(list.stream().map(o -> (String) o).map(Key::key).mapToInt(keyIdMapping).toArray());
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Holder set must either be a tag, a string ID or a list of string IDs");
|
throw new IllegalArgumentException("Holder set must either be a tag, a string ID or a list of string IDs");
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ import lombok.Setter;
|
|||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.cloudburstmc.math.vector.Vector3i;
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket;
|
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.Scoreboard;
|
||||||
import org.geysermc.geyser.scoreboard.ScoreboardUpdater.ScoreboardSession;
|
import org.geysermc.geyser.scoreboard.ScoreboardUpdater.ScoreboardSession;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
@ -70,6 +71,8 @@ public final class WorldCache {
|
|||||||
@Setter
|
@Setter
|
||||||
private boolean editingSignOnFront;
|
private boolean editingSignOnFront;
|
||||||
|
|
||||||
|
private final Object2IntMap<Item> activeCooldowns = new Object2IntOpenHashMap<>(2);
|
||||||
|
|
||||||
public WorldCache(GeyserSession session) {
|
public WorldCache(GeyserSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.scoreboard = new Scoreboard(session);
|
this.scoreboard = new Scoreboard(session);
|
||||||
@ -201,4 +204,32 @@ public final class WorldCache {
|
|||||||
public String removeActiveRecord(Vector3i pos) {
|
public String removeActiveRecord(Vector3i pos) {
|
||||||
return this.activeRecords.remove(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import org.cloudburstmc.math.vector.Vector3d;
|
|||||||
import org.cloudburstmc.math.vector.Vector3f;
|
import org.cloudburstmc.math.vector.Vector3f;
|
||||||
import org.cloudburstmc.math.vector.Vector3i;
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
|
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.BlockDefinition;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
|
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
|
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.ContainerOpenPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.InventoryTransactionPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.InventoryTransactionPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||||
import org.geysermc.geyser.entity.type.Entity;
|
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.EntityUtils;
|
||||||
import org.geysermc.geyser.util.InteractionResult;
|
import org.geysermc.geyser.util.InteractionResult;
|
||||||
import org.geysermc.geyser.util.InventoryUtils;
|
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.object.Direction;
|
||||||
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.entity.player.Hand;
|
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.InteractAction;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction;
|
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.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.inventory.ServerboundContainerClickPacket;
|
||||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket;
|
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket;
|
||||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
|
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
|
||||||
@ -373,6 +378,22 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||||||
break;
|
break;
|
||||||
} else if (packet.getItemInHand().getDefinition() == session.getItemMappings().getStoredItems().writtenBook().getBedrockDefinition()) {
|
} else if (packet.getItemInHand().getDefinition() == session.getItemMappings().getStoredItems().writtenBook().getBedrockDefinition()) {
|
||||||
session.setCurrentBook(packet.getItemInHand());
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,5 +57,7 @@ public class JavaCooldownTranslator extends PacketTranslator<ClientboundCooldown
|
|||||||
bedrockPacket.setCooldownDuration(packet.getCooldownTicks());
|
bedrockPacket.setCooldownDuration(packet.getCooldownTicks());
|
||||||
session.sendUpstreamPacket(bedrockPacket);
|
session.sendUpstreamPacket(bedrockPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session.getWorldCache().setCooldown(item, packet.getCooldownTicks());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,18 +40,25 @@ import net.kyori.adventure.text.serializer.legacy.CharacterAndFormat;
|
|||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
import org.cloudburstmc.nbt.NbtMap;
|
import org.cloudburstmc.nbt.NbtMap;
|
||||||
import org.cloudburstmc.nbt.NbtType;
|
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.TextPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.TextPacket;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.text.*;
|
import org.geysermc.geyser.text.ChatColor;
|
||||||
|
import org.geysermc.geyser.text.ChatDecoration;
|
||||||
|
import org.geysermc.geyser.text.DummyLegacyHoverEventSerializer;
|
||||||
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
|
import org.geysermc.geyser.text.GsonComponentSerializerWrapper;
|
||||||
|
import org.geysermc.geyser.text.MinecraftTranslationRegistry;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.DefaultComponentSerializer;
|
import org.geysermc.mcprotocollib.protocol.data.DefaultComponentSerializer;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.Holder;
|
import org.geysermc.mcprotocollib.protocol.data.game.Holder;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatType;
|
import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatType;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatTypeDecoration;
|
import org.geysermc.mcprotocollib.protocol.data.game.chat.ChatTypeDecoration;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor;
|
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class MessageTranslator {
|
public class MessageTranslator {
|
||||||
// These are used for handling the translations of the messages
|
// These are used for handling the translations of the messages
|
||||||
@ -434,7 +441,7 @@ public class MessageTranslator {
|
|||||||
* Deserialize an NbtMap with a description text component (usually provided from a registry) into a Bedrock-formatted string.
|
* Deserialize an NbtMap with a description text component (usually provided from a registry) into a Bedrock-formatted string.
|
||||||
*/
|
*/
|
||||||
public static String deserializeDescription(GeyserSession session, NbtMap tag) {
|
public static String deserializeDescription(GeyserSession session, NbtMap tag) {
|
||||||
NbtMap description = tag.getCompound("description");
|
Object description = tag.get("description");
|
||||||
Component parsed = componentFromNbtTag(description);
|
Component parsed = componentFromNbtTag(description);
|
||||||
return convertMessage(session, parsed);
|
return convertMessage(session, parsed);
|
||||||
}
|
}
|
||||||
@ -482,7 +489,8 @@ public class MessageTranslator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException("Expected tag to be a literal string, a list of components, or a component object with a text/translate key");
|
GeyserImpl.getInstance().getLogger().error("Expected tag to be a literal string, a list of components, or a component object with a text/translate key: " + nbtTag);
|
||||||
|
return Component.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Component> componentsFromNbtList(List<?> list, Style style) {
|
private static List<Component> componentsFromNbtList(List<?> list, Style style) {
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren