Skip to content

Commit 8283021

Browse files
committed
Deal with plugins that create proxy player objects
As I was writing this I realized it sounded like Bungee support, but it isn't
1 parent 144723a commit 8283021

File tree

1 file changed

+42
-3
lines changed

1 file changed

+42
-3
lines changed

modules/API/src/main/java/com/comphenix/protocol/injector/BukkitUnwrapper.java

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,17 @@
2424
import java.util.Map;
2525
import java.util.concurrent.ConcurrentHashMap;
2626

27+
import org.bukkit.Bukkit;
28+
import org.bukkit.entity.Player;
29+
2730
import com.comphenix.protocol.ProtocolLibrary;
2831
import com.comphenix.protocol.error.ErrorReporter;
2932
import com.comphenix.protocol.error.Report;
3033
import com.comphenix.protocol.error.ReportType;
3134
import com.comphenix.protocol.injector.PacketConstructor.Unwrapper;
3235
import com.comphenix.protocol.reflect.FieldUtils;
3336
import com.comphenix.protocol.reflect.instances.DefaultInstances;
37+
import com.comphenix.protocol.utility.MinecraftReflection;
3438
import com.google.common.primitives.Primitives;
3539

3640
/**
@@ -182,20 +186,55 @@ public Object unwrapItem(Object wrappedObject) {
182186
Report.newBuilder(REPORT_SECURITY_LIMITATION).error(e).callerParam(type)
183187
);
184188
} catch (NoSuchMethodException e) {
189+
// Maybe it's a proxy?
190+
Unwrapper proxyUnwrapper = getProxyUnwrapper(type);
191+
if (proxyUnwrapper != null)
192+
return proxyUnwrapper;
193+
185194
// Try getting the field unwrapper too
186195
Unwrapper fieldUnwrapper = getFieldUnwrapper(type);
187-
188196
if (fieldUnwrapper != null)
189197
return fieldUnwrapper;
190198
else
191199
reporter.reportDetailed(this,
192200
Report.newBuilder(REPORT_CANNOT_FIND_UNWRAP_METHOD).error(e).callerParam(type));
193201
}
194-
202+
195203
// Default method
196204
return null;
197205
}
198-
206+
207+
// Players should /always/ be able to be unwrapped
208+
// We should only get here if the 'Player' is a proxy
209+
private Unwrapper getProxyUnwrapper(final Class<?> type) {
210+
try {
211+
if (Player.class.isAssignableFrom(type)) {
212+
final Method getHandle = MinecraftReflection.getCraftPlayerClass().getMethod("getHandle");
213+
214+
Unwrapper unwrapper = new Unwrapper() {
215+
@Override
216+
public Object unwrapItem(Object wrapped) {
217+
try {
218+
return getHandle.invoke(((Player) wrapped).getPlayer());
219+
} catch (Throwable ex) {
220+
try {
221+
return getHandle.invoke(Bukkit.getPlayer(((Player) wrapped).getUniqueId()));
222+
} catch (ReflectiveOperationException ex1) {
223+
throw new RuntimeException("Failed to unwrap proxy " + wrapped, ex);
224+
}
225+
}
226+
}
227+
};
228+
229+
unwrapperCache.put(type, unwrapper);
230+
return unwrapper;
231+
}
232+
} catch (Throwable ignored) {
233+
}
234+
235+
return null;
236+
}
237+
199238
/**
200239
* Retrieve a cached unwrapper using the handle field.
201240
* @param type - a cached field unwrapper.

0 commit comments

Comments
 (0)