Skip to content

Commit 46f6e76

Browse files
authored
Add BlockEntityType support. (#2111)
1 parent 38bbd76 commit 46f6e76

File tree

3 files changed

+229
-1
lines changed

3 files changed

+229
-1
lines changed

src/main/java/com/comphenix/protocol/events/AbstractStructure.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.bukkit.inventory.MerchantRecipe;
3030
import org.bukkit.potion.PotionEffectType;
3131
import org.bukkit.util.Vector;
32+
import org.jetbrains.annotations.NotNull;
3233

3334
public abstract class AbstractStructure {
3435
protected transient Object handle;
@@ -308,6 +309,31 @@ public StructureModifier<BlockPosition> getBlockPositionModifier() {
308309
BlockPosition.getConverter());
309310
}
310311

312+
/**
313+
* Retrieves a read/write structure for registrable objects.
314+
*
315+
* @param registrableClass The registrable object's class.
316+
* @return A modifier for a registrable objects.
317+
* @see MinecraftReflection#getBlockEntityTypeClass()
318+
*/
319+
public StructureModifier<WrappedRegistrable> getRegistrableModifier(
320+
@NotNull final Class<?> registrableClass
321+
) {
322+
// Convert to and from the Bukkit wrapper
323+
return structureModifier.withType(
324+
registrableClass,
325+
BukkitConverters.getWrappedRegistrable(registrableClass));
326+
}
327+
328+
/**
329+
* Retrieves a read/write structure for BlockEntityType.
330+
* @return A modifier for a BlockEntityType.
331+
*/
332+
public StructureModifier<WrappedRegistrable> getBlockEntityTypeModifier() {
333+
// Convert to and from the Bukkit wrapper
334+
return getRegistrableModifier(MinecraftReflection.getBlockEntityTypeClass());
335+
}
336+
311337
/**
312338
* Retrieves a read/write structure for wrapped ChunkCoordIntPairs.
313339
* @return A modifier for ChunkCoordIntPair.

src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
import org.bukkit.potion.PotionEffect;
7878
import org.bukkit.potion.PotionEffectType;
7979
import org.bukkit.util.Vector;
80+
import org.jetbrains.annotations.NotNull;
8081

8182
import static com.comphenix.protocol.utility.MinecraftReflection.getCraftBukkitClass;
8283
import static com.comphenix.protocol.utility.MinecraftReflection.getMinecraftClass;
@@ -587,7 +588,23 @@ public static EquivalentConverter<WrappedChatComponent> getWrappedChatComponentC
587588
public static EquivalentConverter<WrappedBlockData> getWrappedBlockDataConverter() {
588589
return ignoreNull(handle(WrappedBlockData::getHandle, WrappedBlockData::fromHandle, WrappedBlockData.class));
589590
}
590-
591+
592+
/**
593+
* Retrieve a converter for wrapped block entity type.
594+
* @return Wrapped block entity type.
595+
*/
596+
public static EquivalentConverter<WrappedRegistrable> getWrappedRegistrable(
597+
@NotNull final Class<?> registrableClass
598+
) {
599+
return ignoreNull(
600+
handle(
601+
WrappedRegistrable::getHandle,
602+
handle -> WrappedRegistrable.fromHandle(registrableClass, handle),
603+
WrappedRegistrable.class
604+
)
605+
);
606+
}
607+
591608
/**
592609
* Retrieve a converter for wrapped attribute snapshots.
593610
* @return Wrapped attribute snapshot converter.
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/**
2+
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
3+
* Copyright (C) 2015 dmulloy2
4+
* <p>
5+
* This program is free software; you can redistribute it and/or modify it under the terms of the
6+
* GNU General Public License as published by the Free Software Foundation; either version 2 of
7+
* the License, or (at your option) any later version.
8+
* <p>
9+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11+
* See the GNU General Public License for more details.
12+
* <p>
13+
* You should have received a copy of the GNU General Public License along with this program;
14+
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
15+
* 02111-1307 USA
16+
*/
17+
package com.comphenix.protocol.wrappers;
18+
19+
import com.comphenix.protocol.reflect.FuzzyReflection;
20+
import com.comphenix.protocol.reflect.accessors.Accessors;
21+
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
22+
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
23+
import com.comphenix.protocol.utility.MinecraftReflection;
24+
import org.jetbrains.annotations.NotNull;
25+
26+
import java.util.Map;
27+
import java.util.concurrent.ConcurrentHashMap;
28+
29+
/**
30+
* Represents a wrapper around registrable objects.
31+
*
32+
* @author portlek
33+
*/
34+
public final class WrappedRegistrable extends AbstractWrapper implements ClonableWrapper {
35+
36+
@NotNull
37+
private final Factory factory;
38+
39+
private WrappedRegistrable(
40+
@NotNull final Factory factory,
41+
@NotNull final Object handle
42+
) {
43+
super(factory.registrableClass);
44+
this.factory = factory;
45+
setHandle(handle);
46+
}
47+
48+
@NotNull
49+
public static WrappedRegistrable fromHandle(
50+
@NotNull final Factory factory,
51+
@NotNull final Object handle
52+
) {
53+
return new WrappedRegistrable(factory, handle);
54+
}
55+
56+
@NotNull
57+
public static WrappedRegistrable fromHandle(
58+
@NotNull final Class<?> registrableClass,
59+
@NotNull final Object handle
60+
) {
61+
return fromHandle(Factory.getOrCreate(registrableClass), handle);
62+
}
63+
64+
@NotNull
65+
public static WrappedRegistrable fromClassAndKey(
66+
@NotNull final Class<?> registrableClass,
67+
@NotNull final MinecraftKey key
68+
) {
69+
final Factory factory = Factory.getOrCreate(registrableClass);
70+
return fromHandle(factory, factory.getHandle(key));
71+
}
72+
73+
@NotNull
74+
public static WrappedRegistrable fromClassAndKey(
75+
@NotNull final Class<?> registrableClass,
76+
@NotNull final String key
77+
) {
78+
return fromClassAndKey(registrableClass, new MinecraftKey(key));
79+
}
80+
81+
@NotNull
82+
public static WrappedRegistrable blockEntityType(
83+
@NotNull final MinecraftKey key
84+
) {
85+
return fromClassAndKey(MinecraftReflection.getBlockEntityTypeClass(), key);
86+
}
87+
88+
@NotNull
89+
public static WrappedRegistrable blockEntityType(
90+
@NotNull final String key
91+
) {
92+
return blockEntityType(new MinecraftKey(key));
93+
}
94+
95+
/**
96+
* Gets this registrable object's Minecraft key
97+
*
98+
* @return The Minecraft key
99+
*/
100+
public MinecraftKey getKey() {
101+
return factory.getKey(handle);
102+
}
103+
104+
/**
105+
* Sets this registrable object's Minecraft key
106+
*
107+
* @param key Minecraft key
108+
*/
109+
public void setKey(MinecraftKey key) {
110+
setHandle(factory.getHandle(key));
111+
}
112+
113+
public WrappedRegistrable deepClone() {
114+
return fromHandle(factory, handle);
115+
}
116+
117+
@Override
118+
public String toString() {
119+
return "WrappedRegistrable[handle=" + handle + "]";
120+
}
121+
122+
@Override
123+
public int hashCode() {
124+
final int prime = 31;
125+
int result = 1;
126+
result = prime * result + getKey().hashCode();
127+
return result;
128+
}
129+
130+
@Override
131+
public boolean equals(Object o) {
132+
if (o == this) {
133+
return true;
134+
}
135+
if (!(o instanceof WrappedRegistrable)) {
136+
return false;
137+
}
138+
final WrappedRegistrable that = (WrappedRegistrable) o;
139+
return handle.equals(that.handle) || (getKey() == that.getKey());
140+
}
141+
142+
private static final class Factory {
143+
144+
private static final Map<Class<?>, Factory> CACHE = new ConcurrentHashMap<>();
145+
146+
@NotNull
147+
private final Class<?> registrableClass;
148+
149+
@NotNull
150+
private final WrappedRegistry registry;
151+
152+
@NotNull
153+
private final FieldAccessor fieldAccessor;
154+
155+
private Factory(@NotNull final Class<?> registrableClass) {
156+
this.registrableClass = registrableClass;
157+
this.registry = WrappedRegistry.getRegistry(registrableClass);
158+
this.fieldAccessor = Accessors.getFieldAccessor(
159+
FuzzyReflection.fromClass(registrableClass, true)
160+
.getField(
161+
FuzzyFieldContract.newBuilder()
162+
.typeExact(registrableClass)
163+
.build()
164+
)
165+
);
166+
}
167+
168+
@NotNull
169+
public static Factory getOrCreate(
170+
@NotNull final Class<?> registrableClass
171+
) {
172+
return CACHE.computeIfAbsent(registrableClass, Factory::new);
173+
}
174+
175+
@NotNull
176+
public MinecraftKey getKey(@NotNull final Object handle) {
177+
return registry.getKey(fieldAccessor.get(handle));
178+
}
179+
180+
@NotNull
181+
public Object getHandle(MinecraftKey key) {
182+
return registry.get(key);
183+
}
184+
}
185+
}

0 commit comments

Comments
 (0)