/* * Copyright (c) CovertJaguar, 2014 http://railcraft.info * * This code is the property of CovertJaguar * and may only be used with explicit written * permission unless otherwise specified on the * license page at http://railcraft.info/wiki/info:license. */ package mods.railcraft.common.util.misc; import mods.railcraft.common.plugins.forge.WorldPlugin; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.ForgeDirection; import java.util.*; /** * @author CovertJaguar <http://www.railcraft.info> */ public final class AdjacentTileCache { private static final int DELAY_MIN = 20; private static final int DELAY_MAX = 2400; private static final int DELAY_STEP = 2; private final Timer[] timer = new Timer[6]; private final TileEntity[] cache = new TileEntity[6]; private final int[] delay = new int[6]; private final TileEntity source; private final Set<ICacheListener> listeners = new LinkedHashSet<ICacheListener>(); public AdjacentTileCache(TileEntity tile) { this.source = tile; Arrays.fill(delay, DELAY_MIN); for (int i = 0; i < timer.length; i++) { timer[i] = new Timer(); } } public void addListener(ICacheListener listener) { listeners.add(listener); } private TileEntity searchSide(ForgeDirection side) { return WorldPlugin.getTileEntityOnSide(source.getWorldObj(), source.xCoord, source.yCoord, source.zCoord, side); } public void refresh() { for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { getTileOnSide(side); } } public Map<ForgeDirection, TileEntity> refreshTiles() { Map<ForgeDirection, TileEntity> tiles = new EnumMap<ForgeDirection, TileEntity>(ForgeDirection.class); for (ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { tiles.put(side, getTileOnSide(side)); } return tiles; } public void purge() { Arrays.fill(cache, null); Arrays.fill(delay, DELAY_MIN); for (Timer t : timer) { t.reset(); } for (ICacheListener listener : listeners) { listener.purge(); } } public void onNeighborChange() { Arrays.fill(delay, DELAY_MIN); } protected void setTile(ForgeDirection side, TileEntity tile) { int s = side.ordinal(); if (cache[s] != tile) { cache[s] = tile; changed(side); } } private void changed(ForgeDirection side) { for (ICacheListener listener : listeners) { listener.changed(side); } } private boolean isInSameChunk(ForgeDirection side) { int sx = MiscTools.getXOnSide(source.xCoord, side); int sz = MiscTools.getZOnSide(source.zCoord, side); return source.xCoord >> 4 == sx >> 4 && source.zCoord >> 4 == sz >> 4; } public TileEntity getTileOnSide(ForgeDirection side) { if (Game.IS_BUKKIT || !isInSameChunk(side)) { changed(side); return searchSide(side); } int s = side.ordinal(); if (cache[s] != null) if (cache[s].isInvalid() || !MiscTools.areCoordinatesOnSide(source.xCoord, source.yCoord, source.zCoord, side, cache[s].xCoord, cache[s].yCoord, cache[s].zCoord)) setTile(side, null); else return cache[s]; if (timer[s].hasTriggered(source.getWorldObj(), delay[s])) { setTile(side, searchSide(side)); if (cache[s] == null) incrementDelay(s); else delay[s] = DELAY_MIN; } return cache[s]; } private void incrementDelay(int side) { delay[side] += DELAY_STEP; if (delay[side] > DELAY_MAX) delay[side] = DELAY_MAX; } public List<String> getDebugOutput() { List<String> debug = new ArrayList<String>(); debug.add("Neighbor Cache: " + Arrays.toString(cache)); return debug; } public interface ICacheListener { void changed(ForgeDirection side); void purge(); } }