Add BlockEntityType support. (#2111)

This commit is contained in:
Hasan Demirtaş 2023-05-07 01:18:09 +03:00 committed by GitHub
parent 38bbd764cc
commit 46f6e76f91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 229 additions and 1 deletions

View File

@ -29,6 +29,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractStructure {
protected transient Object handle;
@ -308,6 +309,31 @@ public abstract class AbstractStructure {
BlockPosition.getConverter());
}
/**
* Retrieves a read/write structure for registrable objects.
*
* @param registrableClass The registrable object's class.
* @return A modifier for a registrable objects.
* @see MinecraftReflection#getBlockEntityTypeClass()
*/
public StructureModifier<WrappedRegistrable> getRegistrableModifier(
@NotNull final Class<?> registrableClass
) {
// Convert to and from the Bukkit wrapper
return structureModifier.withType(
registrableClass,
BukkitConverters.getWrappedRegistrable(registrableClass));
}
/**
* Retrieves a read/write structure for BlockEntityType.
* @return A modifier for a BlockEntityType.
*/
public StructureModifier<WrappedRegistrable> getBlockEntityTypeModifier() {
// Convert to and from the Bukkit wrapper
return getRegistrableModifier(MinecraftReflection.getBlockEntityTypeClass());
}
/**
* Retrieves a read/write structure for wrapped ChunkCoordIntPairs.
* @return A modifier for ChunkCoordIntPair.

View File

@ -77,6 +77,7 @@ import org.bukkit.inventory.MerchantRecipe;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import static com.comphenix.protocol.utility.MinecraftReflection.getCraftBukkitClass;
import static com.comphenix.protocol.utility.MinecraftReflection.getMinecraftClass;
@ -587,7 +588,23 @@ public class BukkitConverters {
public static EquivalentConverter<WrappedBlockData> getWrappedBlockDataConverter() {
return ignoreNull(handle(WrappedBlockData::getHandle, WrappedBlockData::fromHandle, WrappedBlockData.class));
}
/**
* Retrieve a converter for wrapped block entity type.
* @return Wrapped block entity type.
*/
public static EquivalentConverter<WrappedRegistrable> getWrappedRegistrable(
@NotNull final Class<?> registrableClass
) {
return ignoreNull(
handle(
WrappedRegistrable::getHandle,
handle -> WrappedRegistrable.fromHandle(registrableClass, handle),
WrappedRegistrable.class
)
);
}
/**
* Retrieve a converter for wrapped attribute snapshots.
* @return Wrapped attribute snapshot converter.

View File

@ -0,0 +1,185 @@
/**
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2015 dmulloy2
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package com.comphenix.protocol.wrappers;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
import com.comphenix.protocol.utility.MinecraftReflection;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Represents a wrapper around registrable objects.
*
* @author portlek
*/
public final class WrappedRegistrable extends AbstractWrapper implements ClonableWrapper {
@NotNull
private final Factory factory;
private WrappedRegistrable(
@NotNull final Factory factory,
@NotNull final Object handle
) {
super(factory.registrableClass);
this.factory = factory;
setHandle(handle);
}
@NotNull
public static WrappedRegistrable fromHandle(
@NotNull final Factory factory,
@NotNull final Object handle
) {
return new WrappedRegistrable(factory, handle);
}
@NotNull
public static WrappedRegistrable fromHandle(
@NotNull final Class<?> registrableClass,
@NotNull final Object handle
) {
return fromHandle(Factory.getOrCreate(registrableClass), handle);
}
@NotNull
public static WrappedRegistrable fromClassAndKey(
@NotNull final Class<?> registrableClass,
@NotNull final MinecraftKey key
) {
final Factory factory = Factory.getOrCreate(registrableClass);
return fromHandle(factory, factory.getHandle(key));
}
@NotNull
public static WrappedRegistrable fromClassAndKey(
@NotNull final Class<?> registrableClass,
@NotNull final String key
) {
return fromClassAndKey(registrableClass, new MinecraftKey(key));
}
@NotNull
public static WrappedRegistrable blockEntityType(
@NotNull final MinecraftKey key
) {
return fromClassAndKey(MinecraftReflection.getBlockEntityTypeClass(), key);
}
@NotNull
public static WrappedRegistrable blockEntityType(
@NotNull final String key
) {
return blockEntityType(new MinecraftKey(key));
}
/**
* Gets this registrable object's Minecraft key
*
* @return The Minecraft key
*/
public MinecraftKey getKey() {
return factory.getKey(handle);
}
/**
* Sets this registrable object's Minecraft key
*
* @param key Minecraft key
*/
public void setKey(MinecraftKey key) {
setHandle(factory.getHandle(key));
}
public WrappedRegistrable deepClone() {
return fromHandle(factory, handle);
}
@Override
public String toString() {
return "WrappedRegistrable[handle=" + handle + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getKey().hashCode();
return result;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof WrappedRegistrable)) {
return false;
}
final WrappedRegistrable that = (WrappedRegistrable) o;
return handle.equals(that.handle) || (getKey() == that.getKey());
}
private static final class Factory {
private static final Map<Class<?>, Factory> CACHE = new ConcurrentHashMap<>();
@NotNull
private final Class<?> registrableClass;
@NotNull
private final WrappedRegistry registry;
@NotNull
private final FieldAccessor fieldAccessor;
private Factory(@NotNull final Class<?> registrableClass) {
this.registrableClass = registrableClass;
this.registry = WrappedRegistry.getRegistry(registrableClass);
this.fieldAccessor = Accessors.getFieldAccessor(
FuzzyReflection.fromClass(registrableClass, true)
.getField(
FuzzyFieldContract.newBuilder()
.typeExact(registrableClass)
.build()
)
);
}
@NotNull
public static Factory getOrCreate(
@NotNull final Class<?> registrableClass
) {
return CACHE.computeIfAbsent(registrableClass, Factory::new);
}
@NotNull
public MinecraftKey getKey(@NotNull final Object handle) {
return registry.getKey(fieldAccessor.get(handle));
}
@NotNull
public Object getHandle(MinecraftKey key) {
return registry.get(key);
}
}
}