Package logisticspipes.proxy.opencomputers.asm

Source Code of logisticspipes.proxy.opencomputers.asm.BaseWrapperClass

package logisticspipes.proxy.opencomputers.asm;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

import li.cil.oc.api.network.Arguments;
import li.cil.oc.api.network.Callback;
import li.cil.oc.api.network.Context;
import li.cil.oc.api.prefab.AbstractValue;
import logisticspipes.LPConstants;
import logisticspipes.LogisticsPipes;
import logisticspipes.pipes.basic.CoreRoutedPipe;
import logisticspipes.pipes.basic.LogisticsTileGenericPipe;
import logisticspipes.proxy.MainProxy;
import logisticspipes.proxy.computers.interfaces.CCCommand;
import logisticspipes.proxy.computers.interfaces.CCDirectCall;
import logisticspipes.proxy.computers.interfaces.CCQueued;
import logisticspipes.proxy.computers.interfaces.ICCTypeWrapped;
import logisticspipes.proxy.computers.objects.CCItemIdentifier.CCItemIdentifierImplementation;
import logisticspipes.proxy.computers.objects.CCItemIdentifierBuilder;
import logisticspipes.proxy.computers.objects.CCItemIdentifierStack.CCItemIdentifierStackImplementation;
import logisticspipes.proxy.computers.objects.LPGlobalCCAccess;
import logisticspipes.proxy.computers.wrapper.CCObjectWrapper;
import logisticspipes.proxy.computers.wrapper.CCWrapperInformation;
import logisticspipes.proxy.computers.wrapper.ICommandWrapper;
import logisticspipes.security.PermissionException;
import logisticspipes.ticks.QueuedTasks;
import logisticspipes.utils.item.ItemIdentifier;
import logisticspipes.utils.item.ItemIdentifierStack;
import logisticspipes.utils.tuples.LPPosition;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;

public abstract class BaseWrapperClass extends AbstractValue {
 
  public static final ICommandWrapper WRAPPER = new ICommandWrapper() {
    private Map<Class<?>, Class<? extends BaseWrapperClass>> map = new HashMap<Class<?>, Class<? extends BaseWrapperClass>>();
    @Override
    public Object getWrappedObject(CCWrapperInformation info, Object object) {
      try {
        Class<? extends BaseWrapperClass> clazz = map.get(object.getClass());
        if(clazz == null) {
          clazz = ClassCreator.getWrapperClass(info, object.getClass().getName());
          map.put(object.getClass(), clazz);
        }
        return clazz.getConstructor(CCWrapperInformation.class, Object.class).newInstance(info, object);
      } catch(Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e);
      }
    }
  };
 
  private final CCWrapperInformation info;
  private Object object;
  public boolean isDirectCall;

  public BaseWrapperClass(String wrappedClass) throws ClassNotFoundException {
    this(CCObjectWrapper.getWrapperInformation(Class.forName(wrappedClass)), null);
  }
 
  public BaseWrapperClass(CCWrapperInformation info, Object object) {
    super();
    this.info = info;
    this.object = object;
  }

  @Callback(direct=true)
  public Object[] help(Context context, Arguments args) throws Exception {
    if(object == null) throw new Exception("This LP object is not persistable");
    StringBuilder help = new StringBuilder();
    StringBuilder head = new StringBuilder();
    StringBuilder head2 = new StringBuilder();
    head.append("Type: ");
    head.append(info.type);
    head.append("\n");
    head2.append("Commands: \n");
    for(Integer num:info.commands.keySet()) {
      Method method = info.commands.get(num);
      StringBuilder command = new StringBuilder();
      if(help.length() != 0) {
        command.append("\n");
      }
      int number = num.intValue();
      if(number < 10) {
        command.append(" ");
      }
      command.append(number);
      command.append(" ");
      if(method.isAnnotationPresent(CCDirectCall.class)) {
        command.append("D");
      } else {
        command.append(" ");
      }
      if(method.isAnnotationPresent(CCQueued.class)) {
        command.append("Q");
      } else {
        command.append(" ");
      }
      command.append(": ");
      command.append(method.getName());
      StringBuilder param = new StringBuilder();
      param.append("(");
      boolean a = false;
      for(Class<?> clazz:method.getParameterTypes()) {
        if(a) {
          param.append(", ");
        }
        param.append(clazz.getSimpleName());
        a = true;
      }
      param.append(")");
      if(param.toString().length() + command.length() > 50) {
        command.append("\n      ---");
      }
      command.append(param.toString());
      help.append(command.toString());
    }
    String commands = help.toString();
    String[] lines = commands.split("\n");
    if(lines.length > 16) {
      int pageNumber = 1;
      if(args.count() > 0) {
        if(args.isDouble(0) || args.isInteger(0)) {
          pageNumber = args.checkInteger(0);
          if(pageNumber < 1) {
            pageNumber = 1;
          }
        }
      }
      StringBuilder page = new StringBuilder();
      page.append(head.toString());
      page.append("Page ");
      page.append(pageNumber);
      page.append(" of ");
      page.append((int)(Math.floor(lines.length / 10) + (lines.length % 10 == 0 ? 0:1)));
      page.append("\n");
      page.append(head2.toString());
      pageNumber--;
      int from = pageNumber * 11;
      int to = pageNumber * 11 + 11;
      for(int i=from;i<to;i++) {
        if(i < lines.length) {
          page.append(lines[i]);
        }
        if(i < to - 1) {
          page.append("\n");
        }
      }
      return new Object[]{page.toString()};
    } else {
      for(int i=0;i<16-lines.length;i++) {
        String buffer = head.toString();
        head = new StringBuilder();
        head.append("\n").append(buffer);
      }
    }
    return new Object[]{new StringBuilder().append(head).append(head2).append(help).toString()};
  }

  @Callback(direct=true)
  public Object[] helpCommand(Context context, Arguments args) throws Exception {
    if(object == null) throw new Exception("This LP object is not persistable");
    if(args.count() != 1) return new Object[]{"Wrong Argument Count"};
    if(!args.isInteger(0)) return new Object[]{"Wrong Argument Type"};
    Integer number = args.checkInteger(0);
    if(!info.commands.containsKey(number)) return new Object[]{"No command with that index"};
    Method method = info.commands.get(number);
    StringBuilder help = new StringBuilder();
    help.append("---------------------------------\n");
    help.append("Command: ");
    help.append(method.getName());
    help.append("\n");
    help.append("Parameter: ");
    if(method.getParameterTypes().length > 0) {
      help.append("\n");
      boolean a = false;
      for(Class<?> clazz:method.getParameterTypes()) {
        if(a) {
          help.append(", ");
        }
        help.append(clazz.getSimpleName());
        a = true;
      }
      help.append("\n");
    } else {
      help.append("NONE\n");
    }
    help.append("Return Type: ");
    help.append(method.getReturnType().getName());
    help.append("\n");
    help.append("Description: \n");
    help.append(method.getAnnotation(CCCommand.class).description());
    return new Object[]{help.toString()};
  }
 
  public String toString() {
    if(object != null) {
      try {
        if(object.getClass().getMethod("toString").getDeclaringClass() != Object.class) {
          return getType() + ": " + object.toString();
        }
        if(object instanceof ICCTypeWrapped) {
          if(((ICCTypeWrapped)object).getObject().getClass().getMethod("toString").getDeclaringClass() != Object.class) {
            return getType() + ": " + ((ICCTypeWrapped)object).getObject().toString();
          }
        }
      } catch(NoSuchMethodException e) {
        if(LPConstants.DEBUG) {
          e.printStackTrace();
        }
      } catch(SecurityException e) {
        if(LPConstants.DEBUG) {
          e.printStackTrace();
        }
      }
    }
    return getType();
  }

  public Object[] invokeMethod(String methodName, Context context, Arguments args) throws Exception {
    if(object == null) throw new Exception("This LP object is not persistable");
   
    int length = args.count();
    Object[] arguments = new Object[length];
    for(int i=0;i<length;i++) {
      if(args.isString(i)) {
        arguments[i] = args.checkString(i);
      } else {
        Object tmp = args.checkAny(i);
        if(tmp instanceof BaseWrapperClass) {
          tmp = ((BaseWrapperClass)tmp).getObject();
        }
        if(tmp instanceof ICCTypeWrapped) {
          tmp = ((ICCTypeWrapped)tmp).getObject();
        }
        arguments[i] = tmp;
      }
    }
   
    Method match = null;
    for(Method method:info.commands.values()) {
      if(!method.getName().equalsIgnoreCase(methodName)) continue;
      if(!argumentsMatch(method, arguments)) continue;
      match = method;
      break;
    }
   
    if(match == null) {
      StringBuilder error = new StringBuilder();
      error.append("No such method.");
      boolean handled = false;
      for(Method method:info.commands.values()) {
        if(!method.getName().equalsIgnoreCase(methodName)) continue;
        if(handled) {
          error.append("\n");
        }
        handled = true;
        error.append(method.getName());
        error.append("(");
        boolean a = false;
        for(Class<?> clazz:method.getParameterTypes()) {
          if(a) {
            error.append(", ");
          }
          error.append(clazz.getName());
          a = true;
        }
        error.append(")");
      }
      if(!handled) {
        error = new StringBuilder();
        error.append("Internal Excption (Code: 1, ");
        error.append(methodName);
        error.append(")");
      }
      throw new UnsupportedOperationException(error.toString());
    }

    if(match.getAnnotation(CCDirectCall.class) != null) {
      if(!isDirectCall) {
        throw new PermissionException();
      }
    }
   
    if(match.getAnnotation(CCCommand.class).needPermission()) {
      if(info.securityMethod != null) {
        try {
          info.securityMethod.invoke(object);
        } catch(InvocationTargetException e) {
          if(e.getTargetException() instanceof Exception) {
            throw (Exception) e.getTargetException();
          }
          throw e;
        }
      }
    }
   
    Object result;
    try {
      result = match.invoke(this.object, arguments);
    } catch(InvocationTargetException e) {
      if(e.getTargetException() instanceof Exception) {
        throw (Exception) e.getTargetException();
      }
      throw e;
    }
    return CCObjectWrapper.createArray(CCObjectWrapper.getWrappedObject(result, WRAPPER));
  }

  private boolean argumentsMatch(Method method, Object[] arguments) {
    int i=0;
    for(Class<?> args:method.getParameterTypes()) {
      if(arguments.length <= i) return false;
      if(!args.isAssignableFrom(arguments[i].getClass())) return false;
      i++;
    }
    return true;
  }

  public String getType() {
    return info.type;
  }

  public Object getObject() {
    return object;
  }

  @Override
  public void load(NBTTagCompound nbt) {
    if(object != null) return;
    String type = nbt.getString("Type");
    if(type.equals("")) return;
    if(type.equals("LPGlobalCCAccess")) {
      object = LogisticsPipes.getComputerLP();
      checkType();
    } else if(type.equals("CoreRoutedPipe")) {
      int x = nbt.getInteger("X");
      int y = nbt.getInteger("Y");
      int z = nbt.getInteger("Z");
      final LPPosition pos = new LPPosition(x, y, z);
      final int dim = nbt.getInteger("Dim");
      QueuedTasks.queueTask(new Callable<Object>() {
        @Override
        public Object call() throws Exception {
          World world = DimensionManager.getWorld(dim);
          if(world != null) {
            TileEntity tile = pos.getTileEntity(world);
            if(tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe)tile).pipe instanceof CoreRoutedPipe) {
              object = ((LogisticsTileGenericPipe)tile).pipe;
              checkType();
            }
          }
          return null;
        }});
    } else if(type.equals("CCItemIdentifierImplementation")) {
      ItemStack stack = ItemStack.loadItemStackFromNBT(nbt);
      if(stack != null) {
        object = new CCItemIdentifierImplementation(ItemIdentifier.get(stack));
        checkType();
      }
    } else if(type.equals("CCItemIdentifierStackImplementation")) {
      ItemStack stack = ItemStack.loadItemStackFromNBT(nbt);
      if(stack != null) {
        object = new CCItemIdentifierStackImplementation(ItemIdentifierStack.getFromStack(stack));
        checkType();
      }
    } else if(type.equals("CCItemIdentifierBuilder")) {
      ItemStack stack = ItemStack.loadItemStackFromNBT(nbt);
      if(stack != null) {
        CCItemIdentifierBuilder builder = new CCItemIdentifierBuilder();
        builder.setItemID(Double.valueOf(Item.getIdFromItem(stack.getItem())));
        builder.setItemData(Double.valueOf(stack.getItemDamage()));
        object = builder;
        checkType();
      }
    } else {
      System.out.println("Unknown type to load");
    }
  }

  @Override
  public void save(NBTTagCompound nbt) {
    if(object == null) return;
    if(object instanceof LPGlobalCCAccess) {
      nbt.setString("Type", "LPGlobalCCAccess");
    } else if(object instanceof CoreRoutedPipe) {
      LPPosition pos = ((CoreRoutedPipe)object).getLPPosition();
      nbt.setString("Type", "CoreRoutedPipe");
      nbt.setInteger("Dim", MainProxy.getDimensionForWorld(((CoreRoutedPipe)object).getWorld()));
      nbt.setInteger("X", pos.getX());
      nbt.setInteger("Y", pos.getY());
      nbt.setInteger("Z", pos.getZ());
    } else if(object instanceof CCItemIdentifierImplementation) {
      nbt.setString("Type", "CCItemIdentifierImplementation");
      ((CCItemIdentifierImplementation)object).getObject().makeNormalStack(1).writeToNBT(nbt);
    } else if(object instanceof CCItemIdentifierStackImplementation) {
      nbt.setString("Type", "CCItemIdentifierStackImplementation");
      ((CCItemIdentifierStackImplementation)object).getObject().makeNormalStack().writeToNBT(nbt);
    } else if(object instanceof CCItemIdentifierBuilder) {
      nbt.setString("Type", "CCItemIdentifierBuilder");
      ((CCItemIdentifierBuilder)object).build().makeNormalStack(1).writeToNBT(nbt);
    } else {
      System.out.println("Couldn't find mapping for: " + object.getClass());
    }
  }

  private void checkType() {
    if(object != null) {
      if(CCObjectWrapper.getWrapperInformation(object.getClass()) != this.info) {
        System.out.println("WrapperInformationTypes didn't match");
        object = null;
      }
    }
  }

  @Override
  public Object[] call(Context context, Arguments arguments) {
    try {
      return help(context, arguments);
    } catch(Exception e) {
      throw new RuntimeException(e);
    }
  }
}
TOP

Related Classes of logisticspipes.proxy.opencomputers.asm.BaseWrapperClass

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.