mirror of https://github.com/GeyserMC/Geyser.git
Merge branch 'feature/1.20.5' into feature/1.20.5
This commit is contained in:
commit
a627333697
|
@ -64,7 +64,7 @@ jobs:
|
|||
with:
|
||||
name: Geyser NeoForge
|
||||
path: geyser/bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar
|
||||
#if-no-files-found: error // TODO 1.20.5 until neoforge updates
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Standalone)
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
|
|
|
@ -68,7 +68,7 @@ jobs:
|
|||
with:
|
||||
name: Geyser NeoForge
|
||||
path: bootstrap/mod/neoforge/build/libs/Geyser-NeoForge.jar
|
||||
#if-no-files-found: error // TODO 1.20.5 - currently no neoforge artifacts
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Standalone)
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
|
||||
if: success()
|
||||
|
|
|
@ -53,10 +53,10 @@ jobs:
|
|||
with:
|
||||
appID: ${{ secrets.RELEASE_APP_ID }}
|
||||
appPrivateKey: ${{ secrets.RELEASE_APP_PK }}
|
||||
# neoforge:Geyser-NeoForge.jar // TODO 1.20.5
|
||||
files: |
|
||||
bungeecord:Geyser-BungeeCord.jar
|
||||
fabric:Geyser-Fabric.jar
|
||||
neoforge:Geyser-NeoForge.jar
|
||||
spigot:Geyser-Spigot.jar
|
||||
standalone:Geyser-Standalone.jar
|
||||
velocity:Geyser-Velocity.jar
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
architectury {
|
||||
common("fabric")
|
||||
//common("neoforge", "fabric") // todo 1.20.5
|
||||
common("neoforge", "fabric")
|
||||
}
|
||||
|
||||
loom {
|
||||
|
|
|
@ -25,6 +25,6 @@
|
|||
"depends": {
|
||||
"fabricloader": ">=0.15.10",
|
||||
"fabric": "*",
|
||||
"minecraft": ">=1.20.4"
|
||||
"minecraft": ">=1.20.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,12 @@ config = "geyser.mixins.json"
|
|||
[[dependencies.geyser_neoforge]]
|
||||
modId="neoforge"
|
||||
type="required"
|
||||
versionRange="[20.4.48-beta,)"
|
||||
versionRange="[20.5.0-beta,)"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
[[dependencies.geyser_neoforge]]
|
||||
modId="minecraft"
|
||||
type="required"
|
||||
versionRange="[1.20,1.21)"
|
||||
versionRange="[1.20.4,1.21)"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
|
@ -25,7 +25,10 @@
|
|||
|
||||
package org.geysermc.geyser.platform.mod.world;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.Holder;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.item.component.BannerPatternLayer;
|
||||
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponentType;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
@ -43,6 +46,7 @@ import net.minecraft.world.item.component.WrittenBookContent;
|
|||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BannerBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BannerPatternLayers;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.LecternBlockEntity;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
|
@ -62,6 +66,7 @@ import org.geysermc.geyser.session.GeyserSession;
|
|||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
@ -217,8 +222,8 @@ public class GeyserModWorldManager extends GeyserWorldManager {
|
|||
|
||||
@NonNull
|
||||
@Override
|
||||
public CompletableFuture<com.github.steveice10.opennbt.tag.builtin.CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
CompletableFuture<com.github.steveice10.opennbt.tag.builtin.CompoundTag> future = new CompletableFuture<>();
|
||||
public CompletableFuture<com.github.steveice10.mc.protocol.data.game.item.component.DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
CompletableFuture<com.github.steveice10.mc.protocol.data.game.item.component.DataComponents> future = new CompletableFuture<>();
|
||||
server.execute(() -> {
|
||||
ServerPlayer player = getPlayer(session);
|
||||
if (player == null) {
|
||||
|
@ -235,7 +240,22 @@ public class GeyserModWorldManager extends GeyserWorldManager {
|
|||
// the banner might have a custom name, both of which a Java client knows and caches
|
||||
ItemStack itemStack = banner.getItem();
|
||||
|
||||
future.complete(null); // todo 1.20.5
|
||||
com.github.steveice10.mc.protocol.data.game.item.component.DataComponents components =
|
||||
new com.github.steveice10.mc.protocol.data.game.item.component.DataComponents(new HashMap<>());
|
||||
|
||||
components.put(DataComponentType.DAMAGE, itemStack.getDamageValue());
|
||||
|
||||
Component customName = itemStack.getComponents().get(DataComponents.CUSTOM_NAME);
|
||||
if (customName != null) {
|
||||
components.put(DataComponentType.CUSTOM_NAME, toKyoriComponent(customName));
|
||||
}
|
||||
|
||||
BannerPatternLayers pattern = itemStack.get(DataComponents.BANNER_PATTERNS);
|
||||
if (pattern != null) {
|
||||
components.put(DataComponentType.BANNER_PATTERNS, toPatternList(pattern));
|
||||
}
|
||||
|
||||
future.complete(components);
|
||||
return;
|
||||
}
|
||||
future.complete(null);
|
||||
|
@ -262,8 +282,7 @@ public class GeyserModWorldManager extends GeyserWorldManager {
|
|||
if (writtenBookContent != null) {
|
||||
return writtenBookContent.pages().stream()
|
||||
.map(Filterable::raw)
|
||||
.map((component) -> Component.Serializer.toJson(component, RegistryAccess.EMPTY))
|
||||
.map((json -> LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty()))))
|
||||
.map(GeyserModWorldManager::fromComponent)
|
||||
.toList();
|
||||
} else {
|
||||
WritableBookContent writableBookContent = itemStack.get(DataComponents.WRITABLE_BOOK_CONTENT);
|
||||
|
@ -275,4 +294,25 @@ public class GeyserModWorldManager extends GeyserWorldManager {
|
|||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
private static String fromComponent(Component component) {
|
||||
String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY);
|
||||
return LEGACY_SERIALIZER.serialize(GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty()));
|
||||
}
|
||||
|
||||
private static net.kyori.adventure.text.Component toKyoriComponent(Component component) {
|
||||
String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY);
|
||||
return GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty());
|
||||
}
|
||||
|
||||
private static List<BannerPatternLayer> toPatternList(BannerPatternLayers patternLayers) {
|
||||
return patternLayers.layers().stream()
|
||||
.map(layer -> {
|
||||
BannerPatternLayer.BannerPattern pattern = new BannerPatternLayer.BannerPattern(
|
||||
layer.pattern().value().assetId().toString(), layer.pattern().value().translationKey()
|
||||
);
|
||||
return new BannerPatternLayer(Holder.ofCustom(pattern), layer.color().getId());
|
||||
})
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
package org.geysermc.geyser.platform.spigot.world.manager;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
@ -39,7 +39,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.geysermc.erosion.bukkit.BukkitLecterns;
|
||||
import org.geysermc.erosion.bukkit.BukkitUtils;
|
||||
import org.geysermc.erosion.bukkit.PickBlockUtils;
|
||||
import org.geysermc.erosion.bukkit.SchedulerUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.level.GameRule;
|
||||
|
@ -205,8 +204,8 @@ public class GeyserSpigotWorldManager extends WorldManager {
|
|||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
CompletableFuture<@Nullable CompoundTag> future = new CompletableFuture<>();
|
||||
public @NonNull CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
CompletableFuture<@Nullable DataComponents> future = new CompletableFuture<>();
|
||||
Player bukkitPlayer;
|
||||
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
|
||||
future.complete(null);
|
||||
|
@ -215,7 +214,7 @@ public class GeyserSpigotWorldManager extends WorldManager {
|
|||
Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z);
|
||||
// Paper 1.19.3 complains about async access otherwise.
|
||||
// java.lang.IllegalStateException: Tile is null, asynchronous access?
|
||||
SchedulerUtils.runTask(this.plugin, () -> future.complete(PickBlockUtils.pickBlock(block)), block);
|
||||
SchedulerUtils.runTask(this.plugin, () -> future.complete(/*PickBlockUtils.pickBlock(block)*/ null), block); // TODO fix erosion once clear how to handle this
|
||||
return future;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ provided("io.netty", "netty-resolver-dns-native-macos")
|
|||
provided("org.ow2.asm", "asm")
|
||||
|
||||
architectury {
|
||||
minecraft = "1.20.4"
|
||||
minecraft = "1.20.5"
|
||||
}
|
||||
|
||||
loom {
|
||||
|
@ -110,7 +110,7 @@ afterEvaluate {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:1.20.5-rc3")
|
||||
minecraft("com.mojang:minecraft:1.20.5")
|
||||
mappings(loom.officialMojangMappings())
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ val basePlatforms = setOf(
|
|||
|
||||
val moddedPlatforms = setOf(
|
||||
projects.fabric,
|
||||
//projects.neoforge, // todo 1.20.5
|
||||
projects.neoforge,
|
||||
projects.mod
|
||||
).map { it.dependencyProject }
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.geysermc.geyser.translator.text.MessageTranslator;
|
|||
public final class EntityDefinitions {
|
||||
public static final EntityDefinition<AllayEntity> ALLAY;
|
||||
public static final EntityDefinition<AreaEffectCloudEntity> AREA_EFFECT_CLOUD;
|
||||
public static final EntityDefinition<ArmadilloEntity> ARMADILLO;
|
||||
public static final EntityDefinition<ArmorStandEntity> ARMOR_STAND;
|
||||
public static final EntityDefinition<TippedArrowEntity> ARROW;
|
||||
public static final EntityDefinition<AxolotlEntity> AXOLOTL;
|
||||
|
@ -770,6 +771,11 @@ public final class EntityDefinitions {
|
|||
|
||||
// Extends ageable
|
||||
{
|
||||
ARMADILLO = EntityDefinition.inherited(ArmadilloEntity::new, ageableEntityBase)
|
||||
.type(EntityType.ARMADILLO)
|
||||
.height(0.65f).width(0.7f)
|
||||
.addTranslator(null)
|
||||
.build();
|
||||
AXOLOTL = EntityDefinition.inherited(AxolotlEntity::new, ageableEntityBase)
|
||||
.type(EntityType.AXOLOTL)
|
||||
.height(0.42f).width(0.7f)
|
||||
|
@ -937,8 +943,7 @@ public final class EntityDefinitions {
|
|||
LLAMA = EntityDefinition.inherited(LlamaEntity::new, chestedHorseEntityBase)
|
||||
.type(EntityType.LLAMA)
|
||||
.height(1.87f).width(0.9f)
|
||||
.addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityDataTypes.STRENGTH, entityMetadata.getValue()))
|
||||
.addTranslator(MetadataType.INT, LlamaEntity::setCarpetedColor)
|
||||
.addTranslator(MetadataType.INT, LlamaEntity::setStrength)
|
||||
.addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityDataTypes.VARIANT, entityMetadata.getValue()))
|
||||
.build();
|
||||
TRADER_LLAMA = EntityDefinition.inherited(TraderLlamaEntity::new, LLAMA)
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f;
|
|||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
|
@ -49,7 +50,7 @@ public class DolphinEntity extends WaterEntity {
|
|||
@NonNull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
|
||||
if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) {
|
||||
if (!itemInHand.isEmpty() && session.getTagCache().is(ItemTag.FISHES, itemInHand)) {
|
||||
return InteractiveTag.FEED;
|
||||
}
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
|
@ -58,7 +59,7 @@ public class DolphinEntity extends WaterEntity {
|
|||
@NonNull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
|
||||
if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) {
|
||||
if (!itemInHand.isEmpty() && session.getTagCache().is(ItemTag.FISHES, itemInHand)) {
|
||||
// Feed
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ArmadilloEntity extends AnimalEntity {
|
||||
public ArmadilloEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ import org.geysermc.geyser.entity.EntityDefinition;
|
|||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
|
||||
|
@ -61,7 +62,7 @@ public class AxolotlEntity extends AnimalEntity {
|
|||
|
||||
@Override
|
||||
public boolean canEat(Item item) {
|
||||
return session.getTagCache().isAxolotlFood(item);
|
||||
return session.getTagCache().is(ItemTag.AXOLOTL_FOOD, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
|
|||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -67,6 +68,6 @@ public class BeeEntity extends AnimalEntity {
|
|||
|
||||
@Override
|
||||
public boolean canEat(Item item) {
|
||||
return session.getTagCache().isFlower(item);
|
||||
return session.getTagCache().is(ItemTag.FLOWERS, item);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
|||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -56,6 +57,6 @@ public class FoxEntity extends AnimalEntity {
|
|||
|
||||
@Override
|
||||
public boolean canEat(Item item) {
|
||||
return session.getTagCache().isFoxFood(item);
|
||||
return session.getTagCache().is(ItemTag.FOX_FOOD, item);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
|||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.type.FlowerItem;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
|
@ -77,7 +77,7 @@ public class MooshroomEntity extends AnimalEntity {
|
|||
} else if (!isBaby && isAlive() && itemInHand.asItem() == Items.SHEARS) {
|
||||
// Shear items
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (isBrown && session.getTagCache().isSmallFlower(itemInHand) && itemInHand.asItem() instanceof FlowerItem) {
|
||||
} else if (isBrown && session.getTagCache().is(ItemTag.SMALL_FLOWERS, itemInHand)) {
|
||||
// ?
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.geysermc.geyser.entity.EntityDefinitions;
|
|||
import org.geysermc.geyser.entity.type.Tickable;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -72,7 +73,7 @@ public class SnifferEntity extends AnimalEntity implements Tickable {
|
|||
|
||||
@Override
|
||||
public boolean canEat(Item item) {
|
||||
return session.getTagCache().isSnifferFood(item);
|
||||
return session.getTagCache().is(ItemTag.SNIFFER_FOOD, item);
|
||||
}
|
||||
|
||||
public void setSnifferState(ObjectEntityMetadata<SnifferState> entityMetadata) {
|
||||
|
|
|
@ -26,18 +26,23 @@
|
|||
package org.geysermc.geyser.entity.type.living.animal.horse;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import lombok.Getter;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class LlamaEntity extends ChestedHorseEntity {
|
||||
/**
|
||||
* Used to calculate inventory size
|
||||
*/
|
||||
@Getter
|
||||
private int strength = 1;
|
||||
|
||||
public LlamaEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
|
@ -45,28 +50,9 @@ public class LlamaEntity extends ChestedHorseEntity {
|
|||
dirtyMetadata.put(EntityDataTypes.CONTAINER_STRENGTH_MODIFIER, 3); // Presumably 3 slots for every 1 strength
|
||||
}
|
||||
|
||||
/**
|
||||
* Color equipped on the llama
|
||||
*/
|
||||
public void setCarpetedColor(IntEntityMetadata entityMetadata) {
|
||||
// Bedrock treats llama decoration as armor
|
||||
MobArmorEquipmentPacket equipmentPacket = new MobArmorEquipmentPacket();
|
||||
equipmentPacket.setRuntimeEntityId(geyserId);
|
||||
// -1 means no armor
|
||||
int carpetIndex = entityMetadata.getPrimitiveValue();
|
||||
if (carpetIndex > -1 && carpetIndex <= 15) {
|
||||
// The damage value is the dye color that Java sends us, for pre-1.16.220
|
||||
// The item is always going to be a carpet
|
||||
equipmentPacket.setChestplate(session.getItemMappings().getCarpets().get(carpetIndex));
|
||||
} else {
|
||||
equipmentPacket.setChestplate(ItemData.AIR);
|
||||
}
|
||||
// Required to fill out the rest of the equipment or Bedrock ignores it, including above else statement if removing armor
|
||||
equipmentPacket.setBoots(ItemData.AIR);
|
||||
equipmentPacket.setHelmet(ItemData.AIR);
|
||||
equipmentPacket.setLeggings(ItemData.AIR);
|
||||
|
||||
session.sendUpstreamPacket(equipmentPacket);
|
||||
public void setStrength(IntEntityMetadata entityMetadata) {
|
||||
strength = MathUtils.constrain(entityMetadata.getPrimitiveValue(), 1, 5);
|
||||
this.dirtyMetadata.put(EntityDataTypes.STRENGTH, strength);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -133,16 +133,29 @@ public class WolfEntity extends TameableEntity {
|
|||
if (itemInHand.asItem() == Items.BONE && !getFlag(EntityFlag.TAMED)) {
|
||||
// Bone and untamed - can tame
|
||||
return InteractiveTag.TAME;
|
||||
} else {
|
||||
if (itemInHand.asItem() instanceof DyeItem item) {
|
||||
}
|
||||
if (getFlag(EntityFlag.TAMED) && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
|
||||
if (itemInHand.asItem() instanceof DyeItem dyeItem) {
|
||||
// If this fails, as of Java Edition 1.18.1, you cannot toggle sit/stand
|
||||
if (item.dyeColor() != this.collarColor) {
|
||||
if (dyeItem.dyeColor() != this.collarColor) {
|
||||
return InteractiveTag.DYE;
|
||||
} else {
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
} else if (getFlag(EntityFlag.TAMED) && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
|
||||
// Tamed and owned by player - can sit/stand
|
||||
return getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
|
||||
}
|
||||
if (itemInHand.asItem() == Items.WOLF_ARMOR && !this.chestplate.isValid() && !getFlag(EntityFlag.BABY)) {
|
||||
return InteractiveTag.EQUIP_WOLF_ARMOR;
|
||||
}
|
||||
if (itemInHand.asItem() == Items.SHEARS && this.chestplate.isValid()) { // TODO: check curse of binding
|
||||
return InteractiveTag.REMOVE_WOLF_ARMOR;
|
||||
}
|
||||
if (Items.WOLF_ARMOR.isValidRepairItem(itemInHand.asItem()) && getFlag(EntityFlag.SITTING) &&
|
||||
this.chestplate.isValid() && this.chestplate.getTag() != null &&
|
||||
this.chestplate.getTag().getInt("Damage") > 0) {
|
||||
return InteractiveTag.REPAIR_WOLF_ARMOR;
|
||||
}
|
||||
// Tamed and owned by player - can sit/stand
|
||||
return getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
|
||||
}
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
|||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
|
@ -65,7 +66,7 @@ public class CreeperEntity extends MonsterEntity {
|
|||
@NonNull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
|
||||
if (session.getTagCache().isCreeperIgniter(itemInHand.asItem())) {
|
||||
if (session.getTagCache().is(ItemTag.CREEPER_IGNITERS, itemInHand)) {
|
||||
return InteractiveTag.IGNITE_CREEPER;
|
||||
} else {
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
|
@ -75,7 +76,7 @@ public class CreeperEntity extends MonsterEntity {
|
|||
@NonNull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
|
||||
if (session.getTagCache().isCreeperIgniter(itemInHand.asItem())) {
|
||||
if (session.getTagCache().is(ItemTag.CREEPER_IGNITERS, itemInHand)) {
|
||||
// Ignite creeper - as of 1.19.3
|
||||
session.playSoundEvent(SoundEvent.IGNITE, position);
|
||||
return InteractionResult.SUCCESS;
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.geysermc.geyser.entity.EntityDefinition;
|
|||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
|
@ -65,7 +66,7 @@ public class PiglinEntity extends BasePiglinEntity {
|
|||
@Override
|
||||
public void updateOffHand(GeyserSession session) {
|
||||
// Check if the Piglin is holding Gold and set the ADMIRING flag accordingly so its pose updates
|
||||
setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(session.getItemMappings().getMapping(this.offHand).getJavaItem()));
|
||||
setFlag(EntityFlag.ADMIRING, session.getTagCache().is(ItemTag.PIGLIN_LOVED, session.getItemMappings().getMapping(this.offHand).getJavaItem()));
|
||||
super.updateBedrockMetadata();
|
||||
|
||||
super.updateOffHand(session);
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
package org.geysermc.geyser.erosion;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.value.PistonValueType;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import io.netty.channel.Channel;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
|
@ -43,7 +43,14 @@ import org.geysermc.erosion.packet.ErosionPacketHandler;
|
|||
import org.geysermc.erosion.packet.ErosionPacketSender;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundInitializePacket;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.*;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundBatchBlockIdPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockEntityPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockIdPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockLookupFailPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockPlacePacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundHandshakePacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundPickBlockPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundPistonEventPacket;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.physics.Direction;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
|
@ -64,7 +71,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
|
|||
@Setter
|
||||
private CompletableFuture<int[]> pendingBatchLookup = null;
|
||||
@Setter
|
||||
private CompletableFuture<CompoundTag> pickBlockLookup = null;
|
||||
private CompletableFuture<DataComponents> pickBlockLookup = null;
|
||||
|
||||
private final AtomicInteger nextTransactionId = new AtomicInteger(1);
|
||||
|
||||
|
@ -140,7 +147,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
|
|||
@Override
|
||||
public void handlePickBlock(GeyserboundPickBlockPacket packet) {
|
||||
if (this.pickBlockLookup != null) {
|
||||
this.pickBlockLookup.complete(packet.getTag());
|
||||
//this.pickBlockLookup.complete(packet.getTag()); // TODO 1.20.5
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
package org.geysermc.geyser.level;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
|
@ -36,7 +36,11 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.erosion.packet.backendbound.*;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockEntityPacket;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundBlockEntityPacket;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundPickBlockPacket;
|
||||
import org.geysermc.erosion.util.BlockPositionIterator;
|
||||
import org.geysermc.erosion.util.LecternUtils;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -174,12 +178,12 @@ public class GeyserWorldManager extends WorldManager {
|
|||
|
||||
@NonNull
|
||||
@Override
|
||||
public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
var erosionHandler = session.getErosionHandler().getAsActive();
|
||||
if (erosionHandler == null) {
|
||||
return super.getPickItemNbt(session, x, y, z, addNbtData);
|
||||
return super.getPickItemComponents(session, x, y, z, addNbtData);
|
||||
}
|
||||
CompletableFuture<CompoundTag> future = new CompletableFuture<>();
|
||||
CompletableFuture<DataComponents> future = new CompletableFuture<>();
|
||||
erosionHandler.setPickBlockLookup(future);
|
||||
erosionHandler.sendPacket(new BackendboundPickBlockPacket(Vector3i.from(x, y, z)));
|
||||
return future;
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
package org.geysermc.geyser.level;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.item.component.DataComponents;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo;
|
||||
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
|
@ -220,7 +220,7 @@ public abstract class WorldManager {
|
|||
* @return expected NBT for this item.
|
||||
*/
|
||||
@NonNull
|
||||
public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addExtraData) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobArmorEquipment
|
|||
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobEquipmentSerializer_v291;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.PlayerHotbarSerializer_v291;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityLinkSerializer_v291;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityMotionSerializer_v291;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v390.serializer.PlayerSkinSerializer_v390;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventoryContentSerializer_v407;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventorySlotSerializer_v407;
|
||||
|
@ -50,7 +51,6 @@ import org.cloudburstmc.protocol.bedrock.packet.CodeBuilderSourcePacket;
|
|||
import org.cloudburstmc.protocol.bedrock.packet.CraftingEventPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.CreatePhotoPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.DebugInfoPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.DisconnectPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.EditorNetworkPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.EntityFallPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.GameTestRequestPacket;
|
||||
|
@ -182,9 +182,18 @@ class CodecProcessor {
|
|||
};
|
||||
|
||||
/**
|
||||
* Serializer that does nothing when trying to deserialize SetEntityMotionPacket since it is not used from the client.
|
||||
* Serializer that does nothing when trying to deserialize SetEntityMotionPacket since it is not used from the client for codec v291.
|
||||
*/
|
||||
private static final BedrockPacketSerializer<SetEntityMotionPacket> SET_ENTITY_MOTION_SERIALIZER = new SetEntityMotionSerializer_v662() {
|
||||
private static final BedrockPacketSerializer<SetEntityMotionPacket> SET_ENTITY_MOTION_SERIALIZER_V291 = new SetEntityMotionSerializer_v291() {
|
||||
@Override
|
||||
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, SetEntityMotionPacket packet) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Serializer that does nothing when trying to deserialize SetEntityMotionPacket since it is not used from the client for codec v662.
|
||||
*/
|
||||
private static final BedrockPacketSerializer<SetEntityMotionPacket> SET_ENTITY_MOTION_SERIALIZER_V662 = new SetEntityMotionSerializer_v662() {
|
||||
@Override
|
||||
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, SetEntityMotionPacket packet) {
|
||||
}
|
||||
|
@ -251,7 +260,9 @@ class CodecProcessor {
|
|||
.updateSerializer(PlayerHotbarPacket.class, PLAYER_HOTBAR_SERIALIZER)
|
||||
.updateSerializer(PlayerSkinPacket.class, PLAYER_SKIN_SERIALIZER)
|
||||
.updateSerializer(SetEntityDataPacket.class, SET_ENTITY_DATA_SERIALIZER)
|
||||
.updateSerializer(SetEntityMotionPacket.class, SET_ENTITY_MOTION_SERIALIZER)
|
||||
.updateSerializer(SetEntityMotionPacket.class, codec.getProtocolVersion() < 662 ?
|
||||
SET_ENTITY_MOTION_SERIALIZER_V291 :
|
||||
SET_ENTITY_MOTION_SERIALIZER_V662)
|
||||
.updateSerializer(SetEntityLinkPacket.class, SET_ENTITY_LINK_SERIALIZER)
|
||||
// Valid serverbound packets where reading of some fields can be skipped
|
||||
.updateSerializer(MobEquipmentPacket.class, MOB_EQUIPMENT_SERIALIZER)
|
||||
|
@ -261,7 +272,6 @@ class CodecProcessor {
|
|||
.updateSerializer(ScriptMessagePacket.class, ILLEGAL_SERIALIZER)
|
||||
// // Ignored bidirectional packets
|
||||
.updateSerializer(ClientCacheStatusPacket.class, IGNORED_SERIALIZER)
|
||||
.updateSerializer(DisconnectPacket.class, IGNORED_SERIALIZER)
|
||||
.updateSerializer(SimpleEventPacket.class, IGNORED_SERIALIZER)
|
||||
.updateSerializer(TickSyncPacket.class, IGNORED_SERIALIZER)
|
||||
.updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER)
|
||||
|
|
|
@ -159,7 +159,6 @@ public class ItemRegistryPopulator {
|
|||
Object2ObjectMap<CustomBlockData, ItemDefinition> customBlockItemDefinitions = new Object2ObjectOpenHashMap<>();
|
||||
|
||||
List<ItemDefinition> buckets = new ObjectArrayList<>();
|
||||
List<ItemData> carpets = new ObjectArrayList<>();
|
||||
|
||||
List<ItemMapping> mappings = new ObjectArrayList<>();
|
||||
// Temporary mapping to create stored items
|
||||
|
@ -458,14 +457,6 @@ public class ItemRegistryPopulator {
|
|||
|
||||
if (javaItem.javaIdentifier().contains("bucket") && !javaItem.javaIdentifier().contains("milk")) {
|
||||
buckets.add(definition);
|
||||
} else if (javaItem.javaIdentifier().contains("_carpet") && !javaItem.javaIdentifier().contains("moss")) {
|
||||
// This should be the numerical order Java sends as an integer value for llamas
|
||||
carpets.add(ItemData.builder()
|
||||
.definition(definition)
|
||||
.damage(mapping.getBedrockData())
|
||||
.count(1)
|
||||
.blockDefinition(mapping.getBedrockBlockDefinition())
|
||||
.build());
|
||||
} else if (javaItem.javaIdentifier().startsWith("minecraft:music_disc_")) {
|
||||
// The Java record level event uses the item ID as the "key" to play the record
|
||||
Registries.RECORDS.register(javaItem.javaId(), SoundEvent.valueOf("RECORD_" +
|
||||
|
@ -589,7 +580,6 @@ public class ItemRegistryPopulator {
|
|||
.storedItems(new StoredItemMappings(javaItemToMapping))
|
||||
.javaOnlyItems(javaOnlyItems)
|
||||
.buckets(buckets)
|
||||
.carpets(carpets)
|
||||
.componentItemData(componentItemData)
|
||||
.lodestoneCompass(lodestoneEntry)
|
||||
.customIdMappings(customIdMappings)
|
||||
|
|
|
@ -69,7 +69,6 @@ public class ItemMappings implements DefinitionRegistry<ItemDefinition> {
|
|||
|
||||
List<ItemDefinition> buckets;
|
||||
List<ItemDefinition> boats;
|
||||
List<ItemData> carpets;
|
||||
|
||||
List<ComponentItemData> componentItemData;
|
||||
Int2ObjectMap<String> customIdMappings;
|
||||
|
@ -99,9 +98,9 @@ public class ItemMappings implements DefinitionRegistry<ItemDefinition> {
|
|||
return javaId >= 0 && javaId < this.items.length ? this.items[javaId] : ItemMapping.AIR;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NonNull
|
||||
public ItemMapping getMapping(Item javaItem) {
|
||||
return getMapping(javaItem.javaIdentifier());
|
||||
return getMapping(javaItem.javaId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,7 +57,7 @@ import java.util.function.ToIntFunction;
|
|||
* Stores any information sent via Java registries. May not contain all data in a given registry - we'll strip what's
|
||||
* unneeded.
|
||||
*
|
||||
* Crafted as of 1.20.5 for easy "add new registry" in the future.
|
||||
* Crafted as of 1.20.5 for easy "add new registry" functionality in the future.
|
||||
*/
|
||||
@Accessors(fluent = true)
|
||||
@Getter
|
||||
|
@ -118,6 +118,7 @@ public final class RegistryCache {
|
|||
REGISTRIES.put("minecraft:" + registry, (registryCache, entries) -> {
|
||||
Int2ObjectMap<T> localCache = localCacheFunction.apply(registryCache);
|
||||
// Clear each local cache every time a new registry entry is given to us
|
||||
// (e.g. proxy server switches)
|
||||
localCache.clear();
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
RegistryEntry entry = entries.get(i);
|
||||
|
|
|
@ -27,64 +27,45 @@ package org.geysermc.geyser.session.cache;
|
|||
|
||||
import com.github.steveice10.mc.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import it.unimi.dsi.fastutil.ints.IntLists;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.registry.type.BlockMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.BlockTag;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Manages information sent from the {@link ClientboundUpdateTagsPacket}. If that packet is not sent, all lists here
|
||||
* will remain empty, matching Java Edition behavior.
|
||||
*
|
||||
* This system is designed for easy extensibility - just add an enum to {@link BlockTag} or {@link ItemTag}.
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
public class TagCache {
|
||||
/* Blocks */
|
||||
private IntList leaves;
|
||||
private IntList wool;
|
||||
public final class TagCache {
|
||||
// Put these here so the enums can load without a static map
|
||||
public static final Map<String, BlockTag> ALL_BLOCK_TAGS = new HashMap<>();
|
||||
public static final Map<String, ItemTag> ALL_ITEM_TAGS = new HashMap<>();
|
||||
|
||||
private IntList axeEffective;
|
||||
private IntList hoeEffective;
|
||||
private IntList pickaxeEffective;
|
||||
private IntList shovelEffective;
|
||||
|
||||
private IntList requiresStoneTool;
|
||||
private IntList requiresIronTool;
|
||||
private IntList requiresDiamondTool;
|
||||
|
||||
/* Items */
|
||||
private IntList axolotlFood;
|
||||
private IntList creeperIgniters;
|
||||
private IntList fishes;
|
||||
private IntList flowers;
|
||||
private IntList foxFood;
|
||||
private IntList piglinLoved;
|
||||
private IntList smallFlowers;
|
||||
private IntList snifferFood;
|
||||
|
||||
public TagCache() {
|
||||
// Ensure all lists are non-null
|
||||
clear();
|
||||
}
|
||||
private final Map<BlockTag, IntList> blocks = new EnumMap<>(BlockTag.class);
|
||||
private final Map<ItemTag, IntList> items = new EnumMap<>(ItemTag.class);
|
||||
|
||||
public void loadPacket(GeyserSession session, ClientboundUpdateTagsPacket packet) {
|
||||
Map<String, int[]> blockTags = packet.getTags().get("minecraft:block");
|
||||
this.leaves = IntList.of(blockTags.get("minecraft:leaves"));
|
||||
this.wool = IntList.of(blockTags.get("minecraft:wool"));
|
||||
|
||||
this.axeEffective = IntList.of(blockTags.get("minecraft:mineable/axe"));
|
||||
this.hoeEffective = IntList.of(blockTags.get("minecraft:mineable/hoe"));
|
||||
this.pickaxeEffective = IntList.of(blockTags.get("minecraft:mineable/pickaxe"));
|
||||
this.shovelEffective = IntList.of(blockTags.get("minecraft:mineable/shovel"));
|
||||
|
||||
this.requiresStoneTool = IntList.of(blockTags.get("minecraft:needs_stone_tool"));
|
||||
this.requiresIronTool = IntList.of(blockTags.get("minecraft:needs_iron_tool"));
|
||||
this.requiresDiamondTool = IntList.of(blockTags.get("minecraft:needs_diamond_tool"));
|
||||
this.blocks.clear();
|
||||
ALL_BLOCK_TAGS.forEach((location, tag) -> {
|
||||
int[] values = blockTags.get(location);
|
||||
if (values != null) {
|
||||
this.blocks.put(tag, IntList.of(values));
|
||||
} else {
|
||||
session.getGeyser().getLogger().debug("Block tag not found from server: " + location);
|
||||
}
|
||||
});
|
||||
|
||||
// Hack btw
|
||||
GeyserLogger logger = session.getGeyser().getLogger();
|
||||
|
@ -96,14 +77,15 @@ public class TagCache {
|
|||
}
|
||||
|
||||
Map<String, int[]> itemTags = packet.getTags().get("minecraft:item");
|
||||
this.axolotlFood = IntList.of(itemTags.get("minecraft:axolotl_food"));
|
||||
this.creeperIgniters = load(itemTags.get("minecraft:creeper_igniters"));
|
||||
this.fishes = IntList.of(itemTags.get("minecraft:fishes"));
|
||||
this.flowers = IntList.of(itemTags.get("minecraft:flowers"));
|
||||
this.foxFood = IntList.of(itemTags.get("minecraft:fox_food"));
|
||||
this.piglinLoved = IntList.of(itemTags.get("minecraft:piglin_loved"));
|
||||
this.smallFlowers = IntList.of(itemTags.get("minecraft:small_flowers"));
|
||||
this.snifferFood = load(itemTags.get("minecraft:sniffer_food"));
|
||||
this.items.clear();
|
||||
ALL_ITEM_TAGS.forEach((location, tag) -> {
|
||||
int[] values = itemTags.get(location);
|
||||
if (values != null) {
|
||||
this.items.put(tag, IntList.of(values));
|
||||
} else {
|
||||
session.getGeyser().getLogger().debug("Item tag not found from server: " + location);
|
||||
}
|
||||
});
|
||||
|
||||
// Hack btw
|
||||
boolean emulatePost1_13Logic = itemTags.get("minecraft:signs").length > 1;
|
||||
|
@ -113,98 +95,32 @@ public class TagCache {
|
|||
}
|
||||
}
|
||||
|
||||
private IntList load(int @Nullable[] tags) {
|
||||
if (tags == null) {
|
||||
return IntLists.EMPTY_LIST;
|
||||
/**
|
||||
* @return true if the block tag is present and contains this block mapping's Java ID.
|
||||
*/
|
||||
public boolean is(BlockTag tag, BlockMapping mapping) {
|
||||
IntList values = this.blocks.get(tag);
|
||||
if (values != null) {
|
||||
return values.contains(mapping.getJavaBlockId());
|
||||
}
|
||||
return IntList.of(tags);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.leaves = IntLists.emptyList();
|
||||
this.wool = IntLists.emptyList();
|
||||
|
||||
this.axeEffective = IntLists.emptyList();
|
||||
this.hoeEffective = IntLists.emptyList();
|
||||
this.pickaxeEffective = IntLists.emptyList();
|
||||
this.shovelEffective = IntLists.emptyList();
|
||||
|
||||
this.requiresStoneTool = IntLists.emptyList();
|
||||
this.requiresIronTool = IntLists.emptyList();
|
||||
this.requiresDiamondTool = IntLists.emptyList();
|
||||
|
||||
this.axolotlFood = IntLists.emptyList();
|
||||
this.creeperIgniters = IntLists.emptyList();
|
||||
this.fishes = IntLists.emptyList();
|
||||
this.flowers = IntLists.emptyList();
|
||||
this.foxFood = IntLists.emptyList();
|
||||
this.piglinLoved = IntLists.emptyList();
|
||||
this.smallFlowers = IntLists.emptyList();
|
||||
this.snifferFood = IntLists.emptyList();
|
||||
/**
|
||||
* @return true if the item tag is present and contains this item stack's Java ID.
|
||||
*/
|
||||
public boolean is(ItemTag tag, GeyserItemStack itemStack) {
|
||||
return is(tag, itemStack.asItem());
|
||||
}
|
||||
|
||||
public boolean isAxolotlFood(Item item) {
|
||||
return axolotlFood.contains(item.javaId());
|
||||
}
|
||||
|
||||
public boolean isCreeperIgniter(Item item) {
|
||||
return creeperIgniters.contains(item.javaId());
|
||||
}
|
||||
|
||||
public boolean isFish(GeyserItemStack itemStack) {
|
||||
return fishes.contains(itemStack.getJavaId());
|
||||
}
|
||||
|
||||
public boolean isFlower(Item item) {
|
||||
return flowers.contains(item.javaId());
|
||||
}
|
||||
|
||||
public boolean isFoxFood(Item item) {
|
||||
return foxFood.contains(item.javaId());
|
||||
}
|
||||
|
||||
public boolean shouldPiglinAdmire(Item item) {
|
||||
return piglinLoved.contains(item.javaId());
|
||||
}
|
||||
|
||||
public boolean isSmallFlower(GeyserItemStack itemStack) {
|
||||
return smallFlowers.contains(itemStack.getJavaId());
|
||||
}
|
||||
|
||||
public boolean isSnifferFood(Item item) {
|
||||
return snifferFood.contains(item.javaId());
|
||||
}
|
||||
|
||||
public boolean isAxeEffective(BlockMapping blockMapping) {
|
||||
return axeEffective.contains(blockMapping.getJavaBlockId());
|
||||
}
|
||||
|
||||
public boolean isHoeEffective(BlockMapping blockMapping) {
|
||||
return hoeEffective.contains(blockMapping.getJavaBlockId());
|
||||
}
|
||||
|
||||
public boolean isPickaxeEffective(BlockMapping blockMapping) {
|
||||
return pickaxeEffective.contains(blockMapping.getJavaBlockId());
|
||||
}
|
||||
|
||||
public boolean isShovelEffective(BlockMapping blockMapping) {
|
||||
return shovelEffective.contains(blockMapping.getJavaBlockId());
|
||||
}
|
||||
|
||||
public boolean isShearsEffective(BlockMapping blockMapping) {
|
||||
int javaBlockId = blockMapping.getJavaBlockId();
|
||||
return leaves.contains(javaBlockId) || wool.contains(javaBlockId);
|
||||
}
|
||||
|
||||
public boolean requiresStoneTool(BlockMapping blockMapping) {
|
||||
return requiresStoneTool.contains(blockMapping.getJavaBlockId());
|
||||
}
|
||||
|
||||
public boolean requiresIronTool(BlockMapping blockMapping) {
|
||||
return requiresIronTool.contains(blockMapping.getJavaBlockId());
|
||||
}
|
||||
|
||||
public boolean requiresDiamondTool(BlockMapping blockMapping) {
|
||||
return requiresDiamondTool.contains(blockMapping.getJavaBlockId());
|
||||
/**
|
||||
* @return true if the item tag is present and contains this item's Java ID.
|
||||
*/
|
||||
public boolean is(ItemTag tag, Item item) {
|
||||
IntList values = this.items.get(tag);
|
||||
if (values != null) {
|
||||
return values.contains(item.javaId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.session.cache.tags;
|
||||
|
||||
import org.geysermc.geyser.session.cache.TagCache;
|
||||
|
||||
public enum BlockTag {
|
||||
LEAVES("leaves"),
|
||||
WOOL("wool"),
|
||||
AXE_EFFECTIVE("mineable/axe"),
|
||||
HOE_EFFECTIVE("mineable/hoe"),
|
||||
PICKAXE_EFFECTIVE("mineable/pickaxe"),
|
||||
SHOVEL_EFFECTIVE("mineable/shovel"),
|
||||
NEEDS_STONE_TOOL("needs_stone_tool"),
|
||||
NEEDS_IRON_TOOL("needs_iron_tool"),
|
||||
NEEDS_DIAMOND_TOOL("needs_diamond_tool");
|
||||
|
||||
BlockTag(String identifier) {
|
||||
register(identifier, this);
|
||||
}
|
||||
|
||||
private static void register(String name, BlockTag tag) {
|
||||
TagCache.ALL_BLOCK_TAGS.put("minecraft:" + name, tag);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.session.cache.tags;
|
||||
|
||||
import org.geysermc.geyser.session.cache.TagCache;
|
||||
|
||||
public enum ItemTag {
|
||||
AXOLOTL_FOOD("axolotl_food"),
|
||||
CREEPER_IGNITERS("creeper_igniters"),
|
||||
FISHES("fishes"),
|
||||
FLOWERS("flowers"),
|
||||
FOX_FOOD("fox_food"),
|
||||
PIGLIN_LOVED("piglin_loved"),
|
||||
SMALL_FLOWERS("small_flowers"),
|
||||
SNIFFER_FOOD("sniffer_food");
|
||||
|
||||
ItemTag(String identifier) {
|
||||
register(identifier, this);
|
||||
}
|
||||
|
||||
private static void register(String name, ItemTag tag) {
|
||||
TagCache.ALL_ITEM_TAGS.put("minecraft:" + name, tag);
|
||||
}
|
||||
}
|
|
@ -47,10 +47,6 @@ public class BiomeTranslator {
|
|||
public static int loadServerBiome(RegistryEntry entry) {
|
||||
String javaIdentifier = entry.getId();
|
||||
return Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, 0);
|
||||
// if (javaId == 0) {
|
||||
// // Matches Java behavior when it sees an invalid biome - it just replaces it with ID 0
|
||||
// biomeTranslations.defaultReturnValue(bedrockId);
|
||||
// }
|
||||
}
|
||||
|
||||
public static BlockStorage toNewBedrockBiome(GeyserSession session, DataPalette biomeData) {
|
||||
|
|
|
@ -43,12 +43,16 @@ public abstract class BlockEntityTranslator {
|
|||
public abstract void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState);
|
||||
|
||||
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) {
|
||||
NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(type), x, y, z);
|
||||
NbtMapBuilder tagBuilder = getConstantBedrockTag(type, x, y, z);
|
||||
translateTag(tagBuilder, tag, blockState);
|
||||
return tagBuilder.build();
|
||||
}
|
||||
|
||||
protected NbtMapBuilder getConstantBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
public static NbtMapBuilder getConstantBedrockTag(BlockEntityType type, int x, int y, int z) {
|
||||
return getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(type), x, y, z);
|
||||
}
|
||||
|
||||
public static NbtMapBuilder getConstantBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return NbtMap.builder()
|
||||
.putInt("x", x)
|
||||
.putInt("y", y)
|
||||
|
|
|
@ -26,9 +26,6 @@
|
|||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.item.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 org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BlockPickRequestPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
|
@ -68,33 +65,23 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator<BlockPic
|
|||
}
|
||||
|
||||
BlockMapping blockMapping = BlockRegistries.JAVA_BLOCKS.getOrDefault(blockToPick, BlockMapping.DEFAULT);
|
||||
boolean addNbtData = packet.isAddUserData() && blockMapping.isBlockEntity(); // Holding down CTRL
|
||||
/*if (BlockStateValues.getBannerColor(blockToPick) != -1 || addNbtData) { //TODO
|
||||
session.getGeyser().getWorldManager().getPickItemNbt(session, vector.getX(), vector.getY(), vector.getZ(), addNbtData)
|
||||
.whenComplete((tag, ex) -> session.ensureInEventLoop(() -> {
|
||||
if (tag == null) {
|
||||
boolean addExtraData = packet.isAddUserData() && blockMapping.isBlockEntity(); // Holding down CTRL
|
||||
if (BlockStateValues.getBannerColor(blockToPick) != -1 || addExtraData) { //TODO
|
||||
session.getGeyser().getWorldManager().getPickItemComponents(session, vector.getX(), vector.getY(), vector.getZ(), addExtraData)
|
||||
.whenComplete((components, ex) -> session.ensureInEventLoop(() -> {
|
||||
if (components == null) {
|
||||
pickItem(session, blockMapping);
|
||||
return;
|
||||
}
|
||||
|
||||
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.getJavaItem().javaId(), 1, tag);
|
||||
ItemStack itemStack = new ItemStack(mapping.getJavaItem().javaId(), 1, components);
|
||||
InventoryUtils.findOrCreateItem(session, itemStack);
|
||||
}));
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
|
||||
pickItem(session, blockMapping);
|
||||
}
|
||||
|
|
|
@ -74,7 +74,8 @@ public class JavaSetEquipmentTranslator extends PacketTranslator<ClientboundSetE
|
|||
livingEntity.setHelmet(item);
|
||||
armorUpdated = true;
|
||||
}
|
||||
case CHESTPLATE -> {
|
||||
case CHESTPLATE, BODY -> {
|
||||
// BODY is sent for llamas with a carpet equipped, as of 1.20.5
|
||||
livingEntity.setChestplate(item);
|
||||
armorUpdated = true;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.Cli
|
|||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateEquipPacket;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
|
@ -114,16 +115,25 @@ public class JavaHorseScreenOpenTranslator extends PacketTranslator<ClientboundH
|
|||
|
||||
// Since 1.20.5, the armor slot is not included in the container size,
|
||||
// but everything is still indexed the same.
|
||||
int slotCount = packet.getNumberOfSlots() + 1;
|
||||
int slotCount = 2; // Don't depend on slot count sent from server
|
||||
|
||||
InventoryTranslator inventoryTranslator;
|
||||
if (entity instanceof LlamaEntity) {
|
||||
if (entity instanceof LlamaEntity llamaEntity) {
|
||||
if (entity.getFlag(EntityFlag.CHESTED)) {
|
||||
slotCount += llamaEntity.getStrength() * 3;
|
||||
}
|
||||
inventoryTranslator = new LlamaInventoryTranslator(slotCount);
|
||||
slots.add(CARPET_SLOT);
|
||||
} else if (entity instanceof ChestedHorseEntity) {
|
||||
if (entity.getFlag(EntityFlag.CHESTED)) {
|
||||
slotCount += 15;
|
||||
}
|
||||
inventoryTranslator = new DonkeyInventoryTranslator(slotCount);
|
||||
slots.add(SADDLE_SLOT);
|
||||
} else if (entity instanceof CamelEntity) {
|
||||
if (entity.getFlag(EntityFlag.CHESTED)) {
|
||||
slotCount += 15;
|
||||
}
|
||||
// The camel has an invisible armor slot and needs special handling, same as the donkey
|
||||
inventoryTranslator = new DonkeyInventoryTranslator(slotCount);
|
||||
slots.add(SADDLE_SLOT);
|
||||
|
|
|
@ -393,10 +393,9 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||
for (BlockEntityInfo blockEntity : blockEntities) {
|
||||
BlockEntityType type = blockEntity.getType();
|
||||
CompoundTag tag = blockEntity.getNbt();
|
||||
if (type == null || tag == null) {
|
||||
if (type == null) {
|
||||
// As an example: ViaVersion will send -1 if it cannot find the block entity type
|
||||
// Vanilla Minecraft gracefully handles this
|
||||
// Since 1.20.5: tags sent here can be null, at which point the block entity is not translated
|
||||
continue;
|
||||
}
|
||||
int x = blockEntity.getX(); // Relative to chunk
|
||||
|
@ -421,8 +420,13 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||
continue;
|
||||
}
|
||||
|
||||
BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(type);
|
||||
bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(session, type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState));
|
||||
if (tag != null) {
|
||||
BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(type);
|
||||
bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(session, type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState));
|
||||
} else {
|
||||
// Since 1.20.5, tags can be null, but Bedrock still needs a default tag to render the item
|
||||
bedrockBlockEntities.add(BlockEntityTranslator.getConstantBedrockTag(type, x + chunkBlockX, y, z + chunkBlockZ).build());
|
||||
}
|
||||
|
||||
// Check for custom skulls
|
||||
// TODO: The tag layout follows new format (profille, etc...)
|
||||
|
|
|
@ -36,17 +36,18 @@ 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.session.cache.tags.BlockTag;
|
||||
import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||
|
||||
public final class BlockUtils {
|
||||
|
||||
private static boolean correctTool(GeyserSession session, BlockMapping blockMapping, String itemToolType) {
|
||||
return switch (itemToolType) {
|
||||
case "axe" -> session.getTagCache().isAxeEffective(blockMapping);
|
||||
case "hoe" -> session.getTagCache().isHoeEffective(blockMapping);
|
||||
case "pickaxe" -> session.getTagCache().isPickaxeEffective(blockMapping);
|
||||
case "shears" -> session.getTagCache().isShearsEffective(blockMapping);
|
||||
case "shovel" -> session.getTagCache().isShovelEffective(blockMapping);
|
||||
case "axe" -> session.getTagCache().is(BlockTag.AXE_EFFECTIVE, blockMapping);
|
||||
case "hoe" -> session.getTagCache().is(BlockTag.HOE_EFFECTIVE, blockMapping);
|
||||
case "pickaxe" -> session.getTagCache().is(BlockTag.PICKAXE_EFFECTIVE, blockMapping);
|
||||
case "shears" -> session.getTagCache().is(BlockTag.LEAVES, blockMapping) || session.getTagCache().is(BlockTag.WOOL, blockMapping);
|
||||
case "shovel" -> session.getTagCache().is(BlockTag.SHOVEL_EFFECTIVE, blockMapping);
|
||||
case "sword" -> blockMapping.getJavaBlockId() == BlockStateValues.JAVA_COBWEB_ID;
|
||||
default -> {
|
||||
session.getGeyser().getLogger().warning("Unknown tool type: " + itemToolType);
|
||||
|
@ -79,15 +80,15 @@ public final class BlockUtils {
|
|||
switch (toolTier) {
|
||||
// Use intentional fall-throughs to check each tier with this block
|
||||
default:
|
||||
if (session.getTagCache().requiresStoneTool(blockMapping)) {
|
||||
if (session.getTagCache().is(BlockTag.NEEDS_STONE_TOOL, blockMapping)) {
|
||||
return false;
|
||||
}
|
||||
case "stone":
|
||||
if (session.getTagCache().requiresIronTool(blockMapping)) {
|
||||
if (session.getTagCache().is(BlockTag.NEEDS_IRON_TOOL, blockMapping)) {
|
||||
return false;
|
||||
}
|
||||
case "iron":
|
||||
if (session.getTagCache().requiresDiamondTool(blockMapping)) {
|
||||
if (session.getTagCache().is(BlockTag.NEEDS_DIAMOND_TOOL, blockMapping)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +132,7 @@ public final class BlockUtils {
|
|||
}
|
||||
|
||||
public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemMapping item, @Nullable DataComponents components, boolean isSessionPlayer) {
|
||||
boolean isShearsEffective = session.getTagCache().isShearsEffective(blockMapping); //TODO called twice
|
||||
boolean isShearsEffective = session.getTagCache().is(BlockTag.LEAVES, blockMapping) || session.getTagCache().is(BlockTag.WOOL, blockMapping); //TODO called twice
|
||||
boolean canHarvestWithHand = blockMapping.isCanBreakWithHand();
|
||||
String toolType = "";
|
||||
String toolTier = "";
|
||||
|
|
|
@ -70,7 +70,10 @@ public enum InteractiveTag {
|
|||
READ,
|
||||
WAKE_VILLAGER("wakevillager"),
|
||||
BARTER,
|
||||
GIVE_ITEM_TO_ALLAY("allay");
|
||||
GIVE_ITEM_TO_ALLAY("allay"),
|
||||
EQUIP_WOLF_ARMOR("equipwolfarmor"),
|
||||
REMOVE_WOLF_ARMOR("removewolfarmor"),
|
||||
REPAIR_WOLF_ARMOR("repairwolfarmor");
|
||||
|
||||
/**
|
||||
* The full string that should be passed on to the client.
|
||||
|
|
|
@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128"
|
|||
raknet = "1.0.0.CR3-20240416.144209-1"
|
||||
blockstateupdater="1.20.80-20240411.142413-1"
|
||||
mcauthlib = "d9d773e"
|
||||
mcprotocollib = "4ee05b62" # Revert from jitpack after release
|
||||
mcprotocollib = "3c81cc80" # Revert from jitpack after release
|
||||
adventure = "4.14.0"
|
||||
adventure-platform = "4.3.0"
|
||||
junit = "5.9.2"
|
||||
|
@ -30,11 +30,11 @@ commodore = "2.2"
|
|||
bungeecord = "a7c6ede"
|
||||
velocity = "3.1.1"
|
||||
viaproxy = "3.2.0-SNAPSHOT"
|
||||
fabric-minecraft = "1.20.4"
|
||||
fabric-loader = "0.15.2"
|
||||
fabric-api = "0.91.2+1.20.4"
|
||||
fabric-minecraft = "1.20.5"
|
||||
fabric-loader = "0.15.10"
|
||||
fabric-api = "0.97.6+1.20.5"
|
||||
fabric-permissions = "0.2-SNAPSHOT"
|
||||
neoforge-minecraft = "20.4.48-beta"
|
||||
neoforge-minecraft = "20.5.0-beta"
|
||||
mixin = "0.8.5"
|
||||
|
||||
# plugin versions
|
||||
|
@ -118,9 +118,9 @@ websocket = { group = "org.java-websocket", name = "Java-WebSocket", version.ref
|
|||
#protocol-common = { group = "org.cloudburstmc.protocol", name = "common", version.ref = "protocol-connection" }
|
||||
#protocol-codec = { group = "org.cloudburstmc.protocol", name = "bedrock-codec", version.ref = "protocol" }
|
||||
#protocol-connection = { group = "org.cloudburstmc.protocol", name = "bedrock-connection", version.ref = "protocol-connection" }
|
||||
protocol-common = { group = "com.github.Kas-tle.Protocol", name = "common", version = "24146ed" } # Remove before merge
|
||||
protocol-codec = { group = "com.github.Kas-tle.Protocol", name = "bedrock-codec", version = "24146ed" } # Remove before merge
|
||||
protocol-connection = { group = "com.github.Kas-tle.Protocol", name = "bedrock-connection", version = "24146ed" } # Remove before merge
|
||||
protocol-common = { group = "com.github.GeyserMC.Protocol", name = "common", version = "ade21be" }
|
||||
protocol-codec = { group = "com.github.GeyserMC.Protocol", name = "bedrock-codec", version = "ade21be" }
|
||||
protocol-connection = { group = "com.github.GeyserMC.Protocol", name = "bedrock-connection", version = "ade21be" }
|
||||
|
||||
math = { group = "org.cloudburstmc.math", name = "immutable", version = "2.0" }
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ include(":ap")
|
|||
include(":api")
|
||||
include(":bungeecord")
|
||||
include(":fabric")
|
||||
//include(":neoforge") // todo 1.20.5
|
||||
include(":neoforge")
|
||||
include(":mod")
|
||||
include(":spigot")
|
||||
include(":standalone")
|
||||
|
@ -78,7 +78,7 @@ include(":core")
|
|||
// Specify project dirs
|
||||
project(":bungeecord").projectDir = file("bootstrap/bungeecord")
|
||||
project(":fabric").projectDir = file("bootstrap/mod/fabric")
|
||||
//project(":neoforge").projectDir = file("bootstrap/mod/neoforge") // todo 1.20.5
|
||||
project(":neoforge").projectDir = file("bootstrap/mod/neoforge")
|
||||
project(":mod").projectDir = file("bootstrap/mod")
|
||||
project(":spigot").projectDir = file("bootstrap/spigot")
|
||||
project(":standalone").projectDir = file("bootstrap/standalone")
|
||||
|
|
Loading…
Reference in New Issue