use of org.spongepowered.api.util.Tuple in project SpongeCommon by SpongePowered.
the class GetterFilterSourceDelegate method write.
@Override
public Tuple<Integer, Integer> write(final ClassWriter cw, final MethodVisitor mv, final ListenerClassVisitor.DiscoveredMethod method, final int paramIdx, int local, final int[] plocals, final ListenerClassVisitor.ListenerParameter[] params) throws ClassNotFoundException {
final Class<?> targetType = method.classByLoader(params[paramIdx].type().getClassName());
final Class<?> eventClass = method.classByLoader(params[0].type().getClassName());
final String targetMethod = this.anno.value();
Method targetMethodObj = null;
try {
targetMethodObj = eventClass.getMethod(targetMethod);
} catch (final NoSuchMethodException e) {
throw new IllegalArgumentException(String.format("Method %s specified by getter annotation was not found in type %s", targetMethod, eventClass.getName()));
}
if (targetMethodObj.getParameterCount() != 0) {
throw new IllegalArgumentException("Method " + targetMethodObj.toGenericString() + " specified by getter annotation has non-zero parameter count");
}
if (!targetMethodObj.getReturnType().equals(Optional.class) && !targetMethodObj.getReturnType().isAssignableFrom(targetType)) {
throw new IllegalArgumentException("Method " + targetMethodObj.toGenericString() + " does not return the correct type. Expected: " + targetType.getName() + " Found: " + targetMethodObj.getReturnType().getName());
}
final Type returnType = Type.getReturnType(targetMethodObj);
final Class<?> declaringClass = targetMethodObj.getDeclaringClass();
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(declaringClass));
final int op = declaringClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL;
mv.visitMethodInsn(op, Type.getInternalName(declaringClass), targetMethod, "()" + returnType.getDescriptor(), declaringClass.isInterface());
final int paramLocal = local++;
mv.visitVarInsn(returnType.getOpcode(ISTORE), paramLocal);
if (!targetMethodObj.getReturnType().isPrimitive()) {
final Label failure = new Label();
final Label success = new Label();
if (Optional.class.equals(targetMethodObj.getReturnType()) && !Optional.class.equals(targetType)) {
// Unwrap the optional
mv.visitVarInsn(ALOAD, paramLocal);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Optional", "isPresent", "()Z", false);
mv.visitJumpInsn(IFEQ, failure);
mv.visitVarInsn(ALOAD, paramLocal);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Optional", "get", "()Ljava/lang/Object;", false);
mv.visitInsn(DUP);
mv.visitVarInsn(ASTORE, paramLocal);
} else {
mv.visitVarInsn(returnType.getOpcode(ILOAD), paramLocal);
}
mv.visitTypeInsn(INSTANCEOF, Type.getInternalName(targetType));
mv.visitJumpInsn(IFNE, success);
mv.visitLabel(failure);
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
mv.visitLabel(success);
}
return new Tuple<>(local, paramLocal);
}
use of org.spongepowered.api.util.Tuple in project SpongeCommon by SpongePowered.
the class GetterFilterSourceDelegate method write.
@Override
public Tuple<Integer, Integer> write(ClassWriter cw, MethodVisitor mv, Method method, Parameter param, int local) {
Class<?> targetType = param.getType();
Class<?> eventClass = method.getParameterTypes()[0];
String targetMethod = this.anno.value();
Method targetMethodObj = null;
try {
targetMethodObj = eventClass.getMethod(targetMethod);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(String.format("Method %s specified by getter annotation was not found in type %s", targetMethod, eventClass.getName()));
}
if (targetMethodObj.getParameterCount() != 0) {
throw new IllegalArgumentException("Method " + targetMethodObj.toGenericString() + " specified by getter annotation has non-zero parameter count");
}
if (!targetMethodObj.getReturnType().equals(Optional.class) && !targetMethodObj.getReturnType().isAssignableFrom(targetType)) {
throw new IllegalArgumentException("Method " + targetMethodObj.toGenericString() + " does not return the correct type. Expected: " + targetType.getName() + " Found: " + targetMethodObj.getReturnType().getName());
}
Type returnType = Type.getReturnType(targetMethodObj);
Class<?> declaringClass = targetMethodObj.getDeclaringClass();
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(declaringClass));
int op = declaringClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL;
mv.visitMethodInsn(op, Type.getInternalName(declaringClass), targetMethod, "()" + returnType.getDescriptor(), declaringClass.isInterface());
int paramLocal = local++;
mv.visitVarInsn(returnType.getOpcode(ISTORE), paramLocal);
if (!targetMethodObj.getReturnType().isPrimitive()) {
Label failure = new Label();
Label success = new Label();
if (Optional.class.equals(targetMethodObj.getReturnType()) && !Optional.class.equals(targetType)) {
// Unwrap the optional
mv.visitVarInsn(ALOAD, paramLocal);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Optional", "isPresent", "()Z", false);
mv.visitJumpInsn(IFEQ, failure);
mv.visitVarInsn(ALOAD, paramLocal);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Optional", "get", "()Ljava/lang/Object;", false);
mv.visitInsn(DUP);
mv.visitVarInsn(ASTORE, paramLocal);
} else {
mv.visitVarInsn(returnType.getOpcode(ILOAD), paramLocal);
}
mv.visitTypeInsn(INSTANCEOF, Type.getInternalName(targetType));
mv.visitJumpInsn(IFNE, success);
mv.visitLabel(failure);
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
mv.visitLabel(success);
}
return new Tuple<>(local, paramLocal);
}
use of org.spongepowered.api.util.Tuple in project SpongeCommon by SpongePowered.
the class FilterGenerator method generateClass.
public byte[] generateClass(String name, Method method) {
name = name.replace('.', '/');
Parameter[] params = method.getParameters();
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
MethodVisitor mv;
cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, name, null, "java/lang/Object", new String[] { Type.getInternalName(EventFilter.class) });
SubtypeFilterDelegate sfilter = null;
List<FilterDelegate> additional = Lists.newArrayList();
boolean cancellation = false;
for (Annotation anno : method.getAnnotations()) {
Object obj = filterFromAnnotation(anno.annotationType());
if (obj == null) {
continue;
}
if (obj instanceof SubtypeFilter) {
if (sfilter != null) {
throw new IllegalStateException("Cannot have both @Include and @Exclude annotations present at once");
}
sfilter = ((SubtypeFilter) obj).getDelegate(anno);
} else if (obj instanceof EventTypeFilter) {
EventTypeFilter etf = (EventTypeFilter) obj;
additional.add(etf.getDelegate(anno));
if (etf == EventTypeFilter.CANCELLATION) {
cancellation = true;
}
}
}
if (!cancellation && Cancellable.class.isAssignableFrom(method.getParameterTypes()[0])) {
additional.add(new CancellationEventFilterDelegate(Tristate.FALSE));
}
if (sfilter != null) {
sfilter.createFields(cw);
}
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
if (sfilter != null) {
sfilter.writeCtor(name, cw, mv);
}
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "filter", "(" + Type.getDescriptor(Event.class) + ")[Ljava/lang/Object;", null, null);
mv.visitCode();
// index of the next available local variable
int local = 2;
if (sfilter != null) {
local = sfilter.write(name, cw, mv, method, local);
}
for (FilterDelegate eventFilter : additional) {
local = eventFilter.write(name, cw, mv, method, local);
}
// local var indices of the parameters values
int[] plocals = new int[params.length - 1];
for (int i = 1; i < params.length; i++) {
Parameter param = params[i];
ParameterFilterSourceDelegate source = null;
List<ParameterFilterDelegate> paramFilters = Lists.newArrayList();
for (Annotation anno : param.getAnnotations()) {
Object obj = filterFromAnnotation(anno.annotationType());
if (obj == null) {
continue;
}
if (obj instanceof ParameterSource) {
if (source != null) {
throw new IllegalStateException("Cannot have multiple parameter filter source annotations (for " + param.getName() + ")");
}
source = ((ParameterSource) obj).getDelegate(anno);
} else if (obj instanceof ParameterFilter) {
paramFilters.add(((ParameterFilter) obj).getDelegate(anno));
}
}
if (source == null) {
throw new IllegalStateException("Cannot have additional parameters filters without a source (for " + param.getName() + ")");
}
if (source instanceof AllCauseFilterSourceDelegate && !paramFilters.isEmpty()) {
// TODO until better handling for filtering arrays is added
throw new IllegalStateException("Cannot have additional parameters filters without an array source (for " + param.getName() + ")");
}
Tuple<Integer, Integer> localState = source.write(cw, mv, method, param, local);
local = localState.getFirst();
plocals[i - 1] = localState.getSecond();
for (ParameterFilterDelegate paramFilter : paramFilters) {
paramFilter.write(cw, mv, method, param, plocals[i - 1]);
}
}
// create the return array
if (params.length == 1) {
mv.visitInsn(ICONST_1);
} else {
mv.visitIntInsn(BIPUSH, params.length);
}
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
// load the event into the array
mv.visitInsn(DUP);
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ALOAD, 1);
mv.visitInsn(AASTORE);
// load all the params into the array
for (int i = 1; i < params.length; i++) {
mv.visitInsn(DUP);
mv.visitIntInsn(BIPUSH, i);
Type paramType = Type.getType(params[i].getType());
mv.visitVarInsn(paramType.getOpcode(ILOAD), plocals[i - 1]);
GeneratorUtils.visitBoxingMethod(mv, paramType);
mv.visitInsn(AASTORE);
}
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
cw.visitEnd();
byte[] data = cw.toByteArray();
if (FILTER_DEBUG) {
File outDir = new File(".sponge.debug.out");
File outFile = new File(outDir, name + ".class");
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}
try (FileOutputStream out = new FileOutputStream(outFile)) {
out.write(data);
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
return data;
}
use of org.spongepowered.api.util.Tuple in project SpongeAPI by SpongePowered.
the class BlockRay method advanceOneBlock.
private boolean advanceOneBlock() {
if (this.direction.getX() == 0) {
if (this.direction.getY() == 0) {
// Only zPlaneT exists
zIntersect();
} else if (this.direction.getZ() == 0) {
// Only yPlaneT exists
yIntersect();
} else {
// yPlaneT and zPlaneT exist
solveIntersections();
}
} else if (this.direction.getY() == 0) {
if (this.direction.getZ() == 0) {
// Only xPlaneT exists
xIntersect();
} else {
// xPlaneT and zPlaneT exist
solveIntersections();
}
} else {
// xPlaneT and yPlaneT exist
solveIntersections();
}
BlockRayHit<E> hit = new BlockRayHit<>(this.extent, this.xCurrent, this.yCurrent, this.zCurrent, this.direction, this.normalCurrent);
// Make sure we actually have a block
if (!hit.mapBlock(Extent::containsBlock)) {
throw new NoSuchElementException("Extent limit reached");
}
// Now if using the narrow phase, test on small selection boxes, if needed
if (this.narrowPhase && !hit.getExtent().getProperty(hit.getBlockPosition(), FullBlockSelectionBoxProperty.class).map(FullBlockSelectionBoxProperty::getValue).orElse(true)) {
// Get the selection box and perform the narrow phase intersection test
final Optional<Tuple<Vector3d, Vector3d>> intersection = hit.mapBlock(Extent::getBlockSelectionBox).flatMap(aabb -> aabb.intersects(this.position, this.direction));
// Create the new narrow hit if there was an intersection
if (intersection.isPresent()) {
final Tuple<Vector3d, Vector3d> pair = intersection.get();
final Vector3d narrowHit = pair.getFirst();
hit = new BlockRayHit<>(this.extent, narrowHit.getX(), narrowHit.getY(), narrowHit.getZ(), this.direction, pair.getSecond());
} else {
// Otherwise return false to attempt the next block
return false;
}
}
// Check the distance limit if in use
if (this.distanceLimit >= 0 && this.position.distanceSquared(hit.getPosition()) > this.distanceLimit * this.distanceLimit) {
throw new NoSuchElementException("Distance limit reached");
}
// Check the block end filter
if (!this.stopFilter.test(hit)) {
throw new NoSuchElementException("Filter limit reached");
}
// Check the block skip filter
if (!this.skipFilter.test(hit)) {
return false;
}
this.hit = hit;
return true;
}
use of org.spongepowered.api.util.Tuple in project SpongeCommon by SpongePowered.
the class VanillaDataStore method serialize.
@Override
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public DataView serialize(DataManipulator dataManipulator, DataView view) {
for (Map.Entry<Key<?>, Tuple<BiConsumer<DataView, ?>, Function<DataView, Optional<?>>>> entry : this.queriesByKey.entrySet()) {
final BiConsumer serializer = entry.getValue().first();
dataManipulator.get((Key) entry.getKey()).ifPresent(value -> serializer.accept(view, value));
}
return view;
}
Aggregations