package mods.eln.sixnode.wirelesssignal; import mods.eln.misc.Coordonate; import mods.eln.sixnode.wirelesssignal.tx.WirelessSignalTxElement; import net.minecraft.block.Block; import net.minecraft.init.Blocks; import java.util.*; import java.util.Map.Entry; public class WirelessUtils { private WirelessUtils() { } public static void getTx(IWirelessSignalSpot root, HashMap<String, HashSet<IWirelessSignalTx>> txSet, HashMap<IWirelessSignalTx, Double> txStrength) { HashSet<IWirelessSignalSpot> spotSet = new HashSet<IWirelessSignalSpot>(); txSet.clear(); txStrength.clear(); getTx(root, txSet, txStrength, spotSet, true, 0); } private static void getTx(IWirelessSignalSpot from, HashMap<String, HashSet<IWirelessSignalTx>> txSet, HashMap<IWirelessSignalTx, Double> txStrength, HashSet<IWirelessSignalSpot> spotSet, boolean isRoot, double strength) { if (spotSet.contains(from)) return; spotSet.add(from); if (!isRoot) { for (List<IWirelessSignalTx> txs : from.getTx().values()) { for (IWirelessSignalTx tx : txs) { if (isRoot) strength = tx.getRange() - getVirtualDistance(tx.getCoordonate(), from.getCoordonate(), tx.getCoordonate().trueDistanceTo(from.getCoordonate())); addTo(tx, strength, txSet, txStrength); } } for (IWirelessSignalSpot spot : from.getSpot()) { if (isRoot) strength = spot.getRange() - getVirtualDistance(spot.getCoordonate(), from.getCoordonate(), spot.getCoordonate().trueDistanceTo(from.getCoordonate())); getTx(spot, txSet, txStrength, spotSet, false, strength); } } else { LinkedList<IWirelessSignalSpot> spots = new LinkedList<IWirelessSignalSpot>(); spots.addAll(from.getSpot()); LinkedList<IWirelessSignalTx> txs = new LinkedList<IWirelessSignalTx>(); for (ArrayList<IWirelessSignalTx> txss : from.getTx().values()) { txs.addAll(txss); } double bestScore; Object best = null; while (!spots.isEmpty() || !txs.isEmpty()) { bestScore = Double.MAX_VALUE; for (IWirelessSignalSpot spot : spots) { double temp = spot.getCoordonate().trueDistanceTo(from.getCoordonate()); if (temp < bestScore) { bestScore = temp; best = spot; } } for (IWirelessSignalTx tx : txs) { double temp = tx.getCoordonate().trueDistanceTo(from.getCoordonate()); if (temp < bestScore) { bestScore = temp; best = tx; } } if (best instanceof IWirelessSignalSpot) { IWirelessSignalSpot b = (IWirelessSignalSpot) best; if (isRoot) strength = b.getRange() - getVirtualDistance(b.getCoordonate(), from.getCoordonate(), b.getCoordonate().trueDistanceTo(from.getCoordonate())); getTx(b, txSet, txStrength, spotSet, false, strength); spots.remove(best); } else if (best == null) { break; } else { IWirelessSignalTx tx = (IWirelessSignalTx) best; if (isRoot) strength = tx.getRange() - getVirtualDistance(tx.getCoordonate(), from.getCoordonate(), tx.getCoordonate().trueDistanceTo(from.getCoordonate())); addTo(tx, strength, txSet, txStrength); txs.remove(best); } } } } private static void addTo(IWirelessSignalTx tx, double strength, Map<String, HashSet<IWirelessSignalTx>> reg, Map<IWirelessSignalTx, Double> txStrength) { String channel = tx.getChannel(); HashSet<IWirelessSignalTx> ch = reg.get(channel); if (ch != null && ch.contains(tx)) return; if (ch == null) reg.put(channel, ch = new HashSet<IWirelessSignalTx>()); ch.add(tx); txStrength.put(tx, strength); } /* * * public static HashSet<IWirelessSignalTx> getTx(String channel,IWirelessSignalSpot root){ HashSet<IWirelessSignalTx> txSet = new HashSet<IWirelessSignalTx>(); getTx(channel, root,txSet); return txSet; } * * private static void getTx(String channel,IWirelessSignalSpot root,HashSet<IWirelessSignalTx> txSet){ for(IWirelessSignalSpot spot : root.getSpot()){ getTx(channel, spot, txSet); } * * if(channel != null){ ArrayList<IWirelessSignalTx> txs = root.getTx().get(channel); if(txs != null) txSet.addAll(txs); }else{ for(ArrayList<IWirelessSignalTx> txs : root.getTx().values()){ txSet.addAll(txs); } } } */ public static WirelessSignalSpot buildSpot(Coordonate c, String channel, int range) { HashMap<String, ArrayList<IWirelessSignalTx>> txs = new HashMap<String, ArrayList<IWirelessSignalTx>>(); ArrayList<IWirelessSignalSpot> spots = new ArrayList<IWirelessSignalSpot>(); for (IWirelessSignalSpot spot : IWirelessSignalSpot.spots) { if (isInRange(spot.getCoordonate(), c, spot.getRange())) { spots.add(spot); } } if (channel != null) { ArrayList<IWirelessSignalTx> inRangeTx = new ArrayList<IWirelessSignalTx>(); List<IWirelessSignalTx> sameChannelTx = WirelessSignalTxElement.channelMap.get(channel); if (sameChannelTx != null) { for (IWirelessSignalTx tx : sameChannelTx) { if (isInRange(tx.getCoordonate(), c, tx.getRange())) { inRangeTx.add(tx); } } } if (!inRangeTx.isEmpty()) txs.put(channel, inRangeTx); } else { for (Entry<String, ArrayList<IWirelessSignalTx>> entryTxs : WirelessSignalTxElement.channelMap.entrySet()) { ArrayList<IWirelessSignalTx> inRangeTx = new ArrayList<IWirelessSignalTx>(); for (IWirelessSignalTx tx : entryTxs.getValue()) { if (isInRange(tx.getCoordonate(), c, tx.getRange())) { inRangeTx.add(tx); } } if (!inRangeTx.isEmpty()) txs.put(entryTxs.getKey(), inRangeTx); } } return new WirelessSignalSpot(txs, spots, c, range); } static private boolean isInRange(Coordonate txC, Coordonate rxC, double range) { double distance = txC.trueDistanceTo(rxC); if (distance > range) return false; if (getVirtualDistance(txC, rxC, distance) > range) return false; return true; } static private double getVirtualDistance(Coordonate txC, Coordonate rxC, double distance) { double virtualDistance = distance; if (distance > 2) { double vx, vy, vz; double dx, dy, dz; vx = rxC.x + 0.5; vy = rxC.y + 0.5; vz = rxC.z + 0.5; dx = (txC.x - rxC.x) / distance; dy = (txC.y - rxC.y) / distance; dz = (txC.z - rxC.z) / distance; Coordonate c = new Coordonate(); c.setDimention(rxC.dimention); for (int idx = 0; idx < distance - 1; idx++) { vx += dx; vy += dy; vz += dz; c.x = (int) vx; c.y = (int) vy; c.z = (int) vz; if (c.getBlockExist()) { Block b = c.getBlock(); if (b != Blocks.air && b.isOpaqueCube()) { virtualDistance += 2.0; } } } } return virtualDistance; } public static class WirelessSignalSpot implements IWirelessSignalSpot { HashMap<String, ArrayList<IWirelessSignalTx>> txs; ArrayList<IWirelessSignalSpot> spots; Coordonate coordonate; int range; public WirelessSignalSpot(HashMap<String, ArrayList<IWirelessSignalTx>> txs, ArrayList<IWirelessSignalSpot> spots, Coordonate coordonate, int range) { this.txs = txs; this.spots = spots; this.coordonate = coordonate; this.range = range; } @Override public HashMap<String, ArrayList<IWirelessSignalTx>> getTx() { return txs; } @Override public ArrayList<IWirelessSignalSpot> getSpot() { return spots; } @Override public Coordonate getCoordonate() { return coordonate; } @Override public int getRange() { return range; } } }