Package nallar.tickthreading.minecraft.tickregion

Source Code of nallar.tickthreading.minecraft.tickregion.TileEntityTickRegion

package nallar.tickthreading.minecraft.tickregion;

import nallar.collections.LinkedHashSetTempSetNoClear;
import nallar.tickthreading.Log;
import nallar.tickthreading.minecraft.TickManager;
import nallar.tickthreading.minecraft.profiling.EntityTickProfiler;
import nallar.tickthreading.util.TableFormatter;
import nallar.tickthreading.util.concurrent.SimpleMutex;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;

import java.util.*;

public class TileEntityTickRegion extends TickRegion {
  private int checkTime = 0;
  private final LinkedHashSetTempSetNoClear<TileEntity> tileEntitySet = new LinkedHashSetTempSetNoClear<TileEntity>();
  public final SimpleMutex lock = new SimpleMutex();
  public SimpleMutex xPlusLock;
  public SimpleMutex xMinusLock;
  public SimpleMutex zPlusLock;
  public SimpleMutex zMinusLock;

  public TileEntityTickRegion(World world, TickManager manager, int regionX, int regionY) {
    super(world, manager, regionX, regionY);
    setupLocks();
  }

  public synchronized void setupLocks() {
    {
      TileEntityTickRegion xPlus = manager.getTileEntityRegion(TickManager.getHashCodeFromRegionCoords(regionX + 1, regionZ));
      if (xPlus != null) {
        synchronized (xPlus) {
          xPlus.xMinusLock = this.lock;
          xPlusLock = xPlus.lock;
        }
      }
    }
    {
      TileEntityTickRegion xMinus = manager.getTileEntityRegion(TickManager.getHashCodeFromRegionCoords(regionX - 1, regionZ));
      if (xMinus != null) {
        synchronized (xMinus) {
          xMinus.xPlusLock = this.lock;
          xMinusLock = xMinus.lock;
        }
      }
    }
    {
      TileEntityTickRegion zPlus = manager.getTileEntityRegion(TickManager.getHashCodeFromRegionCoords(regionX, regionZ + 1));
      if (zPlus != null) {
        synchronized (zPlus) {
          zPlus.zMinusLock = this.lock;
          zPlusLock = zPlus.lock;
        }
      }
    }
    {
      TileEntityTickRegion zMinus = manager.getTileEntityRegion(TickManager.getHashCodeFromRegionCoords(regionX, regionZ - 1));
      if (zMinus != null) {
        synchronized (zMinus) {
          zMinus.zPlusLock = this.lock;
          zMinusLock = zMinus.lock;
        }
      }
    }
  }

  public synchronized void removeLocks() {
    {
      TileEntityTickRegion xPlus = manager.getTileEntityRegion(TickManager.getHashCodeFromRegionCoords(regionX + 1, regionZ));
      if (xPlus != null) {
        synchronized (xPlus) {
          xPlus.xMinusLock = null;
          xPlusLock = null;
        }
      }
    }
    {
      TileEntityTickRegion xMinus = manager.getTileEntityRegion(TickManager.getHashCodeFromRegionCoords(regionX - 1, regionZ));
      if (xMinus != null) {
        synchronized (xMinus) {
          xMinus.xPlusLock = null;
          xMinusLock = null;
        }
      }
    }
    {
      TileEntityTickRegion zPlus = manager.getTileEntityRegion(TickManager.getHashCodeFromRegionCoords(regionX, regionZ + 1));
      if (zPlus != null) {
        synchronized (zPlus) {
          zPlus.zMinusLock = null;
          zPlusLock = null;
        }
      }
    }
    {
      TileEntityTickRegion zMinus = manager.getTileEntityRegion(TickManager.getHashCodeFromRegionCoords(regionX, regionZ - 1));
      if (zMinus != null) {
        synchronized (zMinus) {
          zMinus.zPlusLock = null;
          zMinusLock = null;
        }
      }
    }
  }

  @Override
  public void onRemove() {
    removeLocks();
  }

  @Override
  public boolean run() {
    SimpleMutex xPlusLock = this.xPlusLock;
    if (xPlusLock == null || xPlusLock.tryLock()) {
      try {
        SimpleMutex xMinusLock = this.xMinusLock;
        if (xMinusLock == null || xMinusLock.tryLock()) {
          try {
            SimpleMutex zPlusLock = this.zPlusLock;
            if (zPlusLock == null || zPlusLock.tryLock()) {
              try {
                SimpleMutex zMinusLock = this.zMinusLock;
                if (zMinusLock == null || zMinusLock.tryLock()) {
                  try {
                    return super.run();
                  } finally {
                    if (zMinusLock != null) {
                      zMinusLock.unlock();
                    }
                  }
                }
              } finally {
                if (zPlusLock != null) {
                  zPlusLock.unlock();
                }
              }
            }
          } finally {
            if (xMinusLock != null) {
              xMinusLock.unlock();
            }
          }
        }
      } finally {
        if (xPlusLock != null) {
          xPlusLock.unlock();
        }
      }
    }
    return false;
  }

  @Override
  public void doTick() {
    final TickManager manager = this.manager;
    final boolean check = checkTime++ % 60 == 0;
    final boolean profilingEnabled = manager.profilingEnabled || this.profilingEnabled;
    EntityTickProfiler entityTickProfiler = profilingEnabled ? EntityTickProfiler.ENTITY_TICK_PROFILER : null;
    long startTime = profilingEnabled ? System.nanoTime() : 0;
    final Iterator<TileEntity> tileEntitiesIterator = tileEntitySet.startIteration();
    try {
      while (tileEntitiesIterator.hasNext()) {
        final TileEntity tileEntity = tileEntitiesIterator.next();
        if (check && check(tileEntity, tileEntitiesIterator)) {
          continue;
        }
        try {
          if (tileEntity.isInvalid()) {
            tileEntitiesIterator.remove();
            invalidate(tileEntity);
          } else if (tileEntity.worldObj != null) {
            tileEntity.updateEntity();
          }
        } catch (Throwable throwable) {
          Log.severe("Exception ticking TileEntity " + Log.toString(tileEntity), throwable);
        } finally {
          if (profilingEnabled) {
            long oldStartTime = startTime;
            entityTickProfiler.record(tileEntity, (startTime = System.nanoTime()) - oldStartTime);
          }
        }
      }
    } finally {
      tileEntitySet.done();
    }
  }

  private boolean check(final TileEntity tileEntity, final Iterator tileEntitiesIterator) {
    final int xPos = tileEntity.xCoord;
    final int zPos = tileEntity.zCoord;
    if (TickManager.getHashCode(xPos, zPos) != hashCode) {
      tileEntitiesIterator.remove();
      if (tileEntity.isInvalid() || !world.getChunkProvider().chunkExists(xPos >> 4, zPos >> 4)) {
        if (Log.debug) {
          Log.debug("A tile entity is invalid or unloaded."
              + "\n entity: " + Log.toString(tileEntity)
              + "\n In " + hashCode + "\t.tickRegion: " + tileEntity.tickRegion.hashCode + "\texpected: " + TickManager.getHashCode(xPos, zPos));
        }
        invalidate(tileEntity);
        return true;
      }
      if (Log.debug) {
        Log.debug("A tile entity is in the wrong TickRegion - was it moved by a player, or did something break?"
            + "\n entity: " + Log.toString(tileEntity)
            + "\n In " + hashCode + "\t.tickRegion: " + tileEntity.tickRegion.hashCode + "\texpected: " + TickManager.getHashCode(xPos, zPos));
      }
      manager.add(tileEntity, false);
      return true;
    }
    return tileEntity.lastTTX != xPos || tileEntity.lastTTY != tileEntity.yCoord || tileEntity.lastTTZ != zPos;
  }

  private void invalidate(TileEntity tileEntity) {
    int xPos = tileEntity.xCoord;
    int zPos = tileEntity.zCoord;
    manager.removed(tileEntity);
    Chunk chunk = world.getChunkIfExists(xPos >> 4, zPos >> 4);
    if (chunk != null) {
      chunk.cleanChunkBlockTileEntity(xPos, tileEntity.yCoord, zPos);
    }
  }

  @Override
  protected String getShortTypeName() {
    return "T";
  }

  public boolean add(TileEntity tileEntity) {
    return tileEntitySet.add(tileEntity);
  }

  public boolean remove(TileEntity tileEntity) {
    return tileEntitySet.remove(tileEntity);
  }

  @Override
  public boolean isEmpty() {
    return tileEntitySet.isEmpty();
  }

  @Override
  public int size() {
    return tileEntitySet.size();
  }

  @Override
  public void die() {
    tileEntitySet.clear();
  }

  @Override
  public void dump(final TableFormatter tf) {
    synchronized (tileEntitySet) {
      for (TileEntity e : tileEntitySet) {
        //DumpCommand.dump(tf, e, tf.stringFiller == StringFiller.CHAT ? 35 : 70);
        tf.sb.append("TileEntity ").append(Log.toString(e)).append(" in ").append(hashCode).append(", new ").append(TickManager.getHashCode(e)).append('\n');
      }
    }
  }
}
TOP

Related Classes of nallar.tickthreading.minecraft.tickregion.TileEntityTickRegion

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.