use of mekanism.common.integration.computer.annotation.ComputerMethod in project Mekanism by mekanism.
the class ComputerMethodMapper method collectScanData.
@Override
protected void collectScanData(Map<String, Class<?>> classNameCache, Map<Class<?>, List<AnnotationData>> knownClasses) {
Type wrappingType = Type.getType(WrappingComputerMethod.class);
Map<Class<?>, List<WrappingMethodHelper>> cachedWrappers = new Object2ObjectOpenHashMap<>();
Map<Class<?>, List<MethodDetails>> rawMethodDetails = new Object2ObjectOpenHashMap<>();
for (Entry<Class<?>, List<AnnotationData>> entry : knownClasses.entrySet()) {
Class<?> annotatedClass = entry.getKey();
List<MethodDetails> methodDetails = new ArrayList<>();
rawMethodDetails.put(annotatedClass, methodDetails);
for (AnnotationData data : entry.getValue()) {
if (getAnnotationValue(data, "requiredMods", Collections.<String>emptyList()).stream().anyMatch(s -> !ModList.get().isLoaded(s))) {
// If the required mods are not loaded, skip this annotation as the restrictions are not met
continue;
}
if (data.getTargetType() == ElementType.FIELD) {
// Synthetic Computer Method(s) need to be generated for the field
String fieldName = data.getMemberName();
Field field = getField(annotatedClass, fieldName);
if (field == null) {
continue;
}
if (data.getAnnotationType().equals(wrappingType)) {
// Wrapping computer method
try {
MethodHandle methodHandle = LOOKUP.unreflectGetter(field);
wrapMethodHandle(classNameCache, methodHandle, data, methodDetails, cachedWrappers, annotatedClass, fieldName);
} catch (IllegalAccessException e) {
Mekanism.logger.error("Failed to create getter for field '{}' in class '{}'.", fieldName, annotatedClass.getSimpleName());
}
} else {
String getterName = getAnnotationValue(data, "getter", "");
String setterName = getAnnotationValue(data, "setter", "");
if (getterName.isEmpty() && setterName.isEmpty()) {
Mekanism.logger.error("Field: '{}' in class '{}' is annotated to generate a computer method but does not specify a getter or setter.", fieldName, annotatedClass.getSimpleName());
} else {
MethodRestriction restriction = getAnnotationValue(data, "restriction", MethodRestriction.NONE);
createSyntheticMethod(methodDetails, annotatedClass, field, fieldName, getterName, true, restriction, getAnnotationValue(data, "threadSafeGetter", false));
createSyntheticMethod(methodDetails, annotatedClass, field, fieldName, setterName, false, restriction, getAnnotationValue(data, "threadSafeSetter", false));
}
}
} else {
// data.getTargetType() == ElementType.METHOD
// Note: Signature is methodName followed by the method descriptor
// For example this method is: collectScanDataUnsafe(Ljava/util/Map;Ljava/util/Map;)V
String methodSignature = data.getMemberName();
int descriptorStart = methodSignature.indexOf('(');
if (descriptorStart == -1) {
Mekanism.logger.error("Method '{}' in class '{}' does not have a method descriptor.", methodSignature, annotatedClass.getSimpleName());
} else {
String methodDescriptor = methodSignature.substring(descriptorStart);
String methodName = methodSignature.substring(0, descriptorStart);
Method method = getMethod(annotatedClass, methodName, methodDescriptor);
if (method != null) {
// Note: We need to grab the method handle via the method so that we can access private and protected methods properly
MethodHandle methodHandle;
try {
methodHandle = LOOKUP.unreflect(method);
} catch (IllegalAccessException e) {
Mekanism.logger.error("Failed to retrieve method handle for method '{}' in class '{}'.", methodName, annotatedClass.getSimpleName());
continue;
}
if (data.getAnnotationType().equals(wrappingType)) {
// Wrapping computer method
wrapMethodHandle(classNameCache, methodHandle, data, methodDetails, cachedWrappers, annotatedClass, methodName);
} else {
// ComputerMethod
// See if there is a name override defined for the method, or fallback
String methodNameOverride = getAnnotationValue(data, "nameOverride", methodName, name -> {
if (name.isEmpty()) {
Mekanism.logger.warn("Specified name override for method '{}' in class '{}' is explicitly set to empty and " + "will not be used.", methodName, annotatedClass.getSimpleName());
} else if (validMethodName(name)) {
return true;
} else {
Mekanism.logger.error("Specified name override '{}' for method '{}' in class '{}' is not a valid method name and " + "will not be used.", name, methodName, annotatedClass.getSimpleName());
}
return false;
});
methodDetails.add(new MethodDetails(methodNameOverride, methodHandle, getAnnotationValue(data, "restriction", MethodRestriction.NONE), getAnnotationValue(data, "threadSafe", false)));
}
}
}
}
}
}
List<ClassBasedInfo<MethodDetails>> methodDetails = combineWithParents(rawMethodDetails);
for (ClassBasedInfo<MethodDetails> details : methodDetails) {
// Linked map to preserve order
Map<String, List<MethodHandleInfo>> cache = new LinkedHashMap<>();
details.infoList.sort(Comparator.comparing(info -> info.methodName));
for (MethodDetails handle : details.infoList) {
// Add the method handle to the list of methods with that method name for our computer handler
// Note: we construct the list with an initial capacity of one, as that is likely how many we
// actually have per methodName, we just support using a list
cache.computeIfAbsent(handle.methodName, methodName -> new ArrayList<>(1)).add(new MethodHandleInfo(handle.method, handle.restriction, handle.threadSafe));
}
namedMethodHandleCache.put(details.clazz, cache);
}
}
use of mekanism.common.integration.computer.annotation.ComputerMethod in project Mekanism by mekanism.
the class TileEntityQIORedstoneAdapter method setTargetItem.
@ComputerMethod
private void setTargetItem(ResourceLocation itemName) throws ComputerException {
validateSecurityIsPublic();
Item item = ForgeRegistries.ITEMS.getValue(itemName);
if (item == null || item == Items.AIR) {
throw new ComputerException("Target item '%s' could not be found. If you are trying to clear it consider using clearTargetItem instead.", itemName);
}
handleStackChange(new ItemStack(item));
}
use of mekanism.common.integration.computer.annotation.ComputerMethod in project Mekanism by mekanism.
the class TileEntityDiversionTransporter method decrementMode.
@ComputerMethod
private void decrementMode(Direction side) {
DiversionTransporter transmitter = getTransmitter();
transmitter.updateMode(side, transmitter.modes[side.ordinal()].getPrevious());
}
use of mekanism.common.integration.computer.annotation.ComputerMethod in project Mekanism by mekanism.
the class TileEntityQIOComponent method setFrequency.
@ComputerMethod
private void setFrequency(String name) throws ComputerException {
validateSecurityIsPublic();
QIOFrequency frequency = FrequencyType.QIO.getManagerWrapper().getPublicManager().getFrequency(name);
if (frequency == null) {
throw new ComputerException("No public QIO frequency with name '%s' found.", name);
}
setFrequency(FrequencyType.QIO, frequency.getIdentity(), getOwnerUUID());
}
use of mekanism.common.integration.computer.annotation.ComputerMethod in project Mekanism by mekanism.
the class TileEntityQIOComponent method incrementFrequencyColor.
@ComputerMethod
private void incrementFrequencyColor() throws ComputerException {
validateSecurityIsPublic();
QIOFrequency frequency = computerGetFrequency();
frequency.setColor(frequency.getColor().getNext());
}
Aggregations