Package thaumcraft.api.visnet

Source Code of thaumcraft.api.visnet.VisNetHandler

package thaumcraft.api.visnet;

import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;

import net.minecraft.world.World;
import thaumcraft.api.WorldCoordinates;
import thaumcraft.api.aspects.Aspect;
import cpw.mods.fml.common.FMLLog;

public class VisNetHandler {

  // / NODE DRAINING
  /**
   * This method drains vis from a relay or source near the passed in
   * location. The amount received can be less than the amount requested so
   * take that into account.
   *
   * @param world
   * @param x the x position of the draining block or entity
   * @param y the y position of the draining block or entity
   * @param z the z position of the draining block or entity
   * @param aspect what aspect to drain
   * @param vis how much to drain
   * @return how much was actually drained
   */
  public static int drainVis(World world, int x, int y, int z, Aspect aspect, int amount) {

    int drainedAmount = 0;

    WorldCoordinates drainer = new WorldCoordinates(x, y, z,
        world.provider.dimensionId);
    if (!nearbyNodes.containsKey(drainer)) {
      calculateNearbyNodes(world, x, y, z);
    }

    ArrayList<WeakReference<TileVisNode>> nodes = nearbyNodes.get(drainer);
    if (nodes!=null && nodes.size()>0)
    for (WeakReference<TileVisNode> noderef : nodes) {
     
      TileVisNode node = noderef.get();
     
      if (node == null) continue;

      int a = node.consumeVis(aspect, amount);
      drainedAmount += a;
      amount -= a;
      if (a>0) {
        int color = Aspect.getPrimalAspects().indexOf(aspect);
        generateVisEffect(world.provider.dimensionId, x, y, z, node.xCoord, node.yCoord, node.zCoord, color);       
      }
      if (amount <= 0) {
        break;
      }
    }
   
    return drainedAmount;
  }
 
  static Method generateVisEffect;
  public static void generateVisEffect(int dim, int x, int y, int z, int x2, int y2, int z2, int color) {
    try {
          if(generateVisEffect == null) {
              Class fake = Class.forName("thaumcraft.common.lib.Utils");
              generateVisEffect = fake.getMethod("generateVisEffect", int.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class);
          }
          generateVisEffect.invoke(null, dim, x,y,z,x2,y2,z2,color);
      } catch(Exception ex) {
        FMLLog.warning("[Thaumcraft API] Could not invoke thaumcraft.common.lib.Utils method generateVisEffect");
      }
  }

  public static HashMap<Integer, HashMap<WorldCoordinates, WeakReference<TileVisNode>>> sources = new HashMap<Integer, HashMap<WorldCoordinates, WeakReference<TileVisNode>>>();

  public static void addSource(World world, TileVisNode vs) {
    HashMap<WorldCoordinates, WeakReference<TileVisNode>> sourcelist = sources
        .get(world.provider.dimensionId);
    if (sourcelist == null) {
      sourcelist = new HashMap<WorldCoordinates, WeakReference<TileVisNode>>();
    }
    sourcelist.put(vs.getLocation(), new WeakReference(vs));
    sources.put(world.provider.dimensionId, sourcelist);
    nearbyNodes.clear();
  }

  public static boolean isNodeValid(WeakReference<TileVisNode> node) {
    if (node == null || node.get() == null || node.get().isInvalid())
      return false;
    return true;
  }

  public static WeakReference<TileVisNode> addNode(World world, TileVisNode vn) {
    WeakReference ref = new WeakReference(vn);

    HashMap<WorldCoordinates, WeakReference<TileVisNode>> sourcelist = sources
        .get(world.provider.dimensionId);
    if (sourcelist == null) {
      sourcelist = new HashMap<WorldCoordinates, WeakReference<TileVisNode>>();
      return null;
    }

    ArrayList<Object[]> nearby = new ArrayList<Object[]>();

    for (WeakReference<TileVisNode> root : sourcelist.values()) {
      if (!isNodeValid(root))
        continue;

      TileVisNode source = root.get();

      float r = inRange(world, vn.getLocation(), source.getLocation(),
          vn.getRange());
      if (r > 0) {
        nearby.add(new Object[] { source, r - vn.getRange() * 2 });
      }
      nearby = findClosestNodes(vn, source, nearby);
    }

    float dist = Float.MAX_VALUE;
    TileVisNode closest = null;
    if (nearby.size() > 0) {
      for (Object[] o : nearby) {
        if ((Float) o[1] < dist) {// && canNodeBeSeen(vn,(TileVisNode)
                      // o[0])) {
          dist = (Float) o[1];
          closest = (TileVisNode) o[0];
        }
      }
    }
    if (closest != null) {
      closest.getChildren().add(ref);
      nearbyNodes.clear();
      return new WeakReference(closest);
    }

    return null;
  }

  public static ArrayList<Object[]> findClosestNodes(TileVisNode target,
      TileVisNode root, ArrayList<Object[]> in) {
    TileVisNode closestChild = null;

    for (WeakReference<TileVisNode> child : root.getChildren()) {
      TileVisNode n = child.get();

      if (n != null
          && !n.equals(target)
          && !n.equals(root)
          && (target.getAttunement() == -1 || n.getAttunement() == -1 || n
              .getAttunement() == target.getAttunement())) {

        float r2 = inRange(n.getWorldObj(), n.getLocation(),
            target.getLocation(), target.getRange());
        if (r2 > 0) {
          in.add(new Object[] { n, r2 });
        }

        in = findClosestNodes(target, n, in);
      }
    }
    return in;
  }

  private static float inRange(World world, WorldCoordinates cc1,
      WorldCoordinates cc2, int range) {
    float distance = cc1.getDistanceSquaredToWorldCoordinates(cc2);
    return distance > range * range ? -1 : distance;
  }

  private static HashMap<WorldCoordinates, ArrayList<WeakReference<TileVisNode>>> nearbyNodes = new HashMap<WorldCoordinates, ArrayList<WeakReference<TileVisNode>>>();

  private static void calculateNearbyNodes(World world, int x, int y, int z) {

    HashMap<WorldCoordinates, WeakReference<TileVisNode>> sourcelist = sources
        .get(world.provider.dimensionId);
    if (sourcelist == null) {
      sourcelist = new HashMap<WorldCoordinates, WeakReference<TileVisNode>>();
      return;
    }

    ArrayList<WeakReference<TileVisNode>> cn = new ArrayList<WeakReference<TileVisNode>>();
    WorldCoordinates drainer = new WorldCoordinates(x, y, z,
        world.provider.dimensionId);

    ArrayList<Object[]> nearby = new ArrayList<Object[]>();

    for (WeakReference<TileVisNode> root : sourcelist.values()) {
     
      if (!isNodeValid(root))
        continue;

      TileVisNode source = root.get();
     
      TileVisNode closest = null;
      float range = Float.MAX_VALUE;

      float r = inRange(world, drainer, source.getLocation(),
          source.getRange());
      if (r > 0) {
        range = r;
        closest = source;
      }
     
      ArrayList<WeakReference<TileVisNode>> children = new ArrayList<WeakReference<TileVisNode>>();
      children = getAllChildren(source,children);
     
      for (WeakReference<TileVisNode> child : children) {
        TileVisNode n = child.get();
        if (n != null && !n.equals(root)) {
         
          float r2 = inRange(n.getWorldObj(), n.getLocation(),
              drainer, n.getRange());
          if (r2 > 0 && r2 < range) {
            range = r2;
            closest = n;
          }
        }
      }

      if (closest != null) {
       
        cn.add(new WeakReference(closest));
      }
    }

    nearbyNodes.put(drainer, cn);
  }
 
  private static ArrayList<WeakReference<TileVisNode>> getAllChildren(TileVisNode source, ArrayList<WeakReference<TileVisNode>> list) {
    for (WeakReference<TileVisNode> child : source.getChildren()) {
      TileVisNode n = child.get();
      if (n != null) {
        list.add(child);
        list = getAllChildren(n,list);
      }
    }
    return list;
  }

  // public static boolean canNodeBeSeen(TileVisNode source,TileVisNode
  // target)
  // {
  // double d = Math.sqrt(source.getDistanceFrom(target.xCoord, target.yCoord,
  // target.zCoord));
  // double xd = (source.xCoord-target.xCoord) / d;
  // double yd = (source.yCoord-target.yCoord) / d;
  // double zd = (source.zCoord-target.zCoord) / d;
  // return source.getWorldObj().rayTraceBlocks(
  // Vec3.createVectorHelper(source.xCoord-xd+.5+.5, source.yCoord-yd,
  // source.zCoord-zd),
  // Vec3.createVectorHelper(target.xCoord+.5, target.yCoord+.5,
  // target.zCoord+.5)) == null;
  // }

  // public static HashMap<WorldCoordinates,WeakReference<TileVisNode>>
  // noderef = new HashMap<WorldCoordinates,WeakReference<TileVisNode>>();
  //
  // public static TileVisNode getClosestNodeWithinRadius(World world, int x,
  // int y, int z, int radius) {
  // TileVisNode out = null;
  // WorldCoordinates wc = null;
  // float cd = Float.MAX_VALUE;
  // for (int sx = x - radius; sx <= x + radius; sx++) {
  // for (int sy = y - radius; sy <= y + radius; sy++) {
  // for (int sz = z - radius; sz <= z + radius; sz++) {
  // wc = new WorldCoordinates(sx,sy,sz,world.provider.dimensionId);
  // if (noderef.containsKey(wc)) {
  // float d = wc.getDistanceSquared(x, y, z);
  // if (d<radius*radius && noderef.get(wc).get()!=null &&
  // !noderef.get(wc).get().isReceiver() &&
  // isNodeValid(noderef.get(wc).get().getParent())
  // ) {
  // out = noderef.get(wc).get();
  // cd = d;
  // }
  // }
  // }
  // }
  // }
  // return out;
  // }

}
TOP

Related Classes of thaumcraft.api.visnet.VisNetHandler

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.