Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-19 22:40:18 +01:00
Fix isIncorrectHeldItem check for custom skull blocks
Add defaultBlockState to CustomBlockData
Dieser Commit ist enthalten in:
Ursprung
2ca368019c
Commit
36f540f401
@ -46,6 +46,8 @@ public interface CustomBlockData {
|
|||||||
|
|
||||||
@NonNull List<CustomBlockPermutation> permutations();
|
@NonNull List<CustomBlockPermutation> permutations();
|
||||||
|
|
||||||
|
@NonNull CustomBlockState defaultBlockState();
|
||||||
|
|
||||||
CustomBlockState.@NonNull Builder blockStateBuilder();
|
CustomBlockState.@NonNull Builder blockStateBuilder();
|
||||||
|
|
||||||
interface Builder {
|
interface Builder {
|
||||||
|
@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
|||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
|
import lombok.Value;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.geyser.api.block.custom.component.BoxComponent;
|
import org.geysermc.geyser.api.block.custom.component.BoxComponent;
|
||||||
import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents;
|
import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents;
|
||||||
@ -38,16 +39,17 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Value
|
||||||
public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
||||||
private final BoxComponent selectionBox;
|
BoxComponent selectionBox;
|
||||||
private final BoxComponent collisionBox;
|
BoxComponent collisionBox;
|
||||||
private final String geometry;
|
String geometry;
|
||||||
private final Map<String, MaterialInstance> materialInstances;
|
Map<String, MaterialInstance> materialInstances;
|
||||||
private final Float destroyTime;
|
Float destroyTime;
|
||||||
private final Float friction;
|
Float friction;
|
||||||
private final Integer lightEmission;
|
Integer lightEmission;
|
||||||
private final Integer lightDampening;
|
Integer lightDampening;
|
||||||
private final RotationComponent rotation;
|
RotationComponent rotation;
|
||||||
|
|
||||||
private GeyserCustomBlockComponents(CustomBlockComponentsBuilder builder) {
|
private GeyserCustomBlockComponents(CustomBlockComponentsBuilder builder) {
|
||||||
this.selectionBox = builder.selectionBox;
|
this.selectionBox = builder.selectionBox;
|
||||||
|
@ -26,8 +26,7 @@
|
|||||||
package org.geysermc.geyser.level.block;
|
package org.geysermc.geyser.level.block;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.*;
|
import it.unimi.dsi.fastutil.objects.*;
|
||||||
import lombok.AccessLevel;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.geyser.Constants;
|
import org.geysermc.geyser.Constants;
|
||||||
@ -43,7 +42,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class GeyserCustomBlockData implements CustomBlockData {
|
public class GeyserCustomBlockData implements CustomBlockData {
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
@ -51,6 +49,43 @@ public class GeyserCustomBlockData implements CustomBlockData {
|
|||||||
Map<String, CustomBlockProperty<?>> properties;
|
Map<String, CustomBlockProperty<?>> properties;
|
||||||
List<CustomBlockPermutation> permutations;
|
List<CustomBlockPermutation> permutations;
|
||||||
|
|
||||||
|
@EqualsAndHashCode.Exclude // Otherwise this will a StackOverflowError in hashCode/equals
|
||||||
|
CustomBlockState defaultBlockState;
|
||||||
|
|
||||||
|
private GeyserCustomBlockData(CustomBlockDataBuilder builder) {
|
||||||
|
this.name = builder.name;
|
||||||
|
if (name == null) {
|
||||||
|
throw new IllegalStateException("Name must be set");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.components = builder.components;
|
||||||
|
|
||||||
|
Object2ObjectMap<String, Object> defaultProperties;
|
||||||
|
if (!builder.properties.isEmpty()) {
|
||||||
|
this.properties = Object2ObjectMaps.unmodifiable(new Object2ObjectArrayMap<>(builder.properties));
|
||||||
|
defaultProperties = new Object2ObjectOpenHashMap<>(this.properties.size());
|
||||||
|
for (CustomBlockProperty<?> property : properties.values()) {
|
||||||
|
if (property.values().isEmpty() || property.values().size() > 16) {
|
||||||
|
throw new IllegalStateException(property.name() + " must contain 1 to 16 values.");
|
||||||
|
}
|
||||||
|
if (property.values().stream().distinct().count() != property.values().size()) {
|
||||||
|
throw new IllegalStateException(property.name() + " has duplicate values.");
|
||||||
|
}
|
||||||
|
defaultProperties.put(property.name(), property.values().get(0));
|
||||||
|
}
|
||||||
|
this.defaultBlockState = new GeyserCustomBlockState(this, Object2ObjectMaps.unmodifiable(defaultProperties));
|
||||||
|
} else {
|
||||||
|
this.properties = Object2ObjectMaps.emptyMap();
|
||||||
|
this.defaultBlockState = new GeyserCustomBlockState(this, Object2ObjectMaps.emptyMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!builder.permutations.isEmpty()) {
|
||||||
|
this.permutations = ObjectLists.unmodifiable(new ObjectArrayList<>(builder.permutations));
|
||||||
|
} else {
|
||||||
|
this.permutations = ObjectLists.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NonNull String name() {
|
public @NonNull String name() {
|
||||||
return name;
|
return name;
|
||||||
@ -76,6 +111,11 @@ public class GeyserCustomBlockData implements CustomBlockData {
|
|||||||
return permutations;
|
return permutations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull CustomBlockState defaultBlockState() {
|
||||||
|
return defaultBlockState;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CustomBlockState.@NotNull Builder blockStateBuilder() {
|
public CustomBlockState.@NotNull Builder blockStateBuilder() {
|
||||||
return new GeyserCustomBlockState.CustomBlockStateBuilder(this);
|
return new GeyserCustomBlockState.CustomBlockStateBuilder(this);
|
||||||
@ -125,29 +165,7 @@ public class GeyserCustomBlockData implements CustomBlockData {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CustomBlockData build() {
|
public CustomBlockData build() {
|
||||||
if (name == null) {
|
return new GeyserCustomBlockData(this);
|
||||||
throw new IllegalStateException("Name must be set");
|
|
||||||
}
|
|
||||||
|
|
||||||
Object2ObjectMap<String, CustomBlockProperty<?>> properties = Object2ObjectMaps.emptyMap();
|
|
||||||
if (!this.properties.isEmpty()) {
|
|
||||||
properties = Object2ObjectMaps.unmodifiable(new Object2ObjectArrayMap<>(this.properties));
|
|
||||||
for (CustomBlockProperty<?> property : properties.values()) {
|
|
||||||
if (property.values().isEmpty() || property.values().size() > 16) {
|
|
||||||
throw new IllegalStateException(property.name() + " must contain 1 to 16 values.");
|
|
||||||
}
|
|
||||||
if (property.values().stream().distinct().count() != property.values().size()) {
|
|
||||||
throw new IllegalStateException(property.name() + " has duplicate values.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<CustomBlockPermutation> permutations = ObjectLists.emptyList();
|
|
||||||
if (!this.permutations.isEmpty()) {
|
|
||||||
permutations = ObjectLists.unmodifiable(new ObjectArrayList<>(this.permutations));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GeyserCustomBlockData(name, components, properties, permutations);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,7 +350,7 @@ public class BlockRegistryPopulator {
|
|||||||
.putString("value", components.geometry())
|
.putString("value", components.geometry())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
if (components.materialInstances() != null && !components.materialInstances().isEmpty()) {
|
if (!components.materialInstances().isEmpty()) {
|
||||||
NbtMapBuilder materialsBuilder = NbtMap.builder();
|
NbtMapBuilder materialsBuilder = NbtMap.builder();
|
||||||
for (Map.Entry<String, MaterialInstance> entry : components.materialInstances().entrySet()) {
|
for (Map.Entry<String, MaterialInstance> entry : components.materialInstances().entrySet()) {
|
||||||
MaterialInstance materialInstance = entry.getValue();
|
MaterialInstance materialInstance = entry.getValue();
|
||||||
|
@ -84,13 +84,6 @@ public class CustomSkull {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CustomBlockState getDefaultBlockState() {
|
|
||||||
return customBlockData.blockStateBuilder()
|
|
||||||
.intProperty(BITS_A_PROPERTY, 0)
|
|
||||||
.intProperty(BITS_B_PROPERTY, 0)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomBlockState getWallBlockState(int wallDirection) {
|
public CustomBlockState getWallBlockState(int wallDirection) {
|
||||||
wallDirection = switch (wallDirection) {
|
wallDirection = switch (wallDirection) {
|
||||||
case 0 -> 2; // South
|
case 0 -> 2; // South
|
||||||
|
@ -38,6 +38,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
|||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
||||||
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
||||||
import org.geysermc.geyser.api.util.TriState;
|
import org.geysermc.geyser.api.util.TriState;
|
||||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||||
@ -276,16 +277,24 @@ public abstract class ItemTranslator {
|
|||||||
*/
|
*/
|
||||||
public static int getBedrockItemId(GeyserSession session, @Nonnull GeyserItemStack itemStack) {
|
public static int getBedrockItemId(GeyserSession session, @Nonnull GeyserItemStack itemStack) {
|
||||||
if (itemStack.isEmpty()) {
|
if (itemStack.isEmpty()) {
|
||||||
return ItemMapping.AIR.getJavaId();
|
return ItemMapping.AIR.getBedrockId();
|
||||||
}
|
}
|
||||||
int javaId = itemStack.getJavaId();
|
int javaId = itemStack.getJavaId();
|
||||||
ItemMapping mapping = ITEM_STACK_TRANSLATORS.getOrDefault(javaId, DEFAULT_TRANSLATOR)
|
ItemMapping mapping = ITEM_STACK_TRANSLATORS.getOrDefault(javaId, DEFAULT_TRANSLATOR)
|
||||||
.getItemMapping(javaId, itemStack.getNbt(), session.getItemMappings());
|
.getItemMapping(javaId, itemStack.getNbt(), session.getItemMappings());
|
||||||
|
|
||||||
|
int itemId = mapping.getBedrockId();
|
||||||
|
if (mapping == session.getItemMappings().getStoredItems().playerHead()) {
|
||||||
|
CustomSkull customSkull = getCustomSkull(session, itemStack.getNbt());
|
||||||
|
if (customSkull != null) {
|
||||||
|
itemId = session.getItemMappings().getCustomBlockItemIds().getInt(customSkull.getCustomBlockData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int customItemId = getCustomItem(itemStack.getNbt(), mapping);
|
int customItemId = getCustomItem(itemStack.getNbt(), mapping);
|
||||||
if (customItemId == -1) {
|
if (customItemId == -1) {
|
||||||
// No custom item
|
// No custom item
|
||||||
return mapping.getBedrockId();
|
return itemId;
|
||||||
} else {
|
} else {
|
||||||
return customItemId;
|
return customItemId;
|
||||||
}
|
}
|
||||||
@ -556,29 +565,34 @@ public abstract class ItemTranslator {
|
|||||||
builder.blockRuntimeId(0);
|
builder.blockRuntimeId(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void translatePlayerHead(GeyserSession session, CompoundTag nbt, ItemData.Builder builder) {
|
private static CustomSkull getCustomSkull(GeyserSession session, CompoundTag nbt) {
|
||||||
if (nbt != null && nbt.contains("SkullOwner")) {
|
if (nbt != null && nbt.contains("SkullOwner")) {
|
||||||
if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) {
|
if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) {
|
||||||
// It's a username give up d:
|
// It's a username give up d:
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner);
|
SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner);
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt);
|
session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1);
|
String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1);
|
||||||
|
return BlockRegistries.CUSTOM_SKULLS.get(skinHash);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
CustomSkull customSkull = BlockRegistries.CUSTOM_SKULLS.get(skinHash);
|
private static void translatePlayerHead(GeyserSession session, CompoundTag nbt, ItemData.Builder builder) {
|
||||||
if (customSkull != null) {
|
CustomSkull customSkull = getCustomSkull(session, nbt);
|
||||||
int itemId = session.getItemMappings().getCustomBlockItemIds().getInt(customSkull.getCustomBlockData());
|
if (customSkull != null) {
|
||||||
int blockRuntimeId = session.getBlockMappings().getCustomBlockStateIds().getInt(customSkull.getDefaultBlockState());
|
CustomBlockData customBlockData = customSkull.getCustomBlockData();
|
||||||
|
int itemId = session.getItemMappings().getCustomBlockItemIds().getInt(customBlockData);
|
||||||
|
int blockRuntimeId = session.getBlockMappings().getCustomBlockStateIds().getInt(customBlockData.defaultBlockState());
|
||||||
|
|
||||||
builder.id(itemId);
|
builder.id(itemId);
|
||||||
builder.blockRuntimeId(blockRuntimeId);
|
builder.blockRuntimeId(blockRuntimeId);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren