Skip to content

Commit

Permalink
Completely Rewrote Chunky Turtle
Browse files Browse the repository at this point in the history
  • Loading branch information
darichey committed Jan 22, 2016
1 parent dcea935 commit 5b89e7d
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 179 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ public void init(FMLInitializationEvent event) {
registerUpgrade(new TurtleNoteBlock());
registerUpgrade(new TurtleRidable());
registerUpgrade(new TurtleDispenser());
registerUpgrade(new TurtleChunkLoader());
registerUpgrade(new TurtleResupply());
registerUpgrade(new TurtleChunkLoader());
LOGGER.info("Registering pocket computer upgrades...");
try {
ComputerCraftRegistry.registerPocketUpgrade(new PocketMotionDetector());
Expand All @@ -137,13 +137,14 @@ public void init(FMLInitializationEvent event) {
proxy.setupVillagers();
EntityRegistry.registerModEntity(EntityRidableTurtle.class, "Ridable Turtle", 1, instance, 64, 1, true);
EntityRegistry.registerModEntity(EntityNanoBotSwarm.class, "NanoBotSwarm", 2, instance, 64, 20, true);

ForgeChunkManager.setForcedChunkLoadingCallback(PeripheralsPlusPlus.instance, new PeripheralChunkLoader.LoaderHandler());
}

@Mod.EventHandler
public void postInit(FMLPostInitializationEvent event) throws ComputerCraftNotFoundException {
Recipes.init();
BlockDispenser.dispenseBehaviorRegistry.putObject(ModItems.nanoSwarm, new ItemNanoSwarm.BehaviorNanoSwarm());
ForgeChunkManager.setForcedChunkLoadingCallback(this, new PeripheralChunkLoader.TurtleChunkLoadingCallback());
SimpleRunnable.RESTRICT_THREAD_USAGE = false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,7 @@ public class Config {
public static boolean enableChunkyTurtle = true;

@Description(category = "Chunky Turtle", comment = "Radius of chunks that will be loaded. 0 for 1x1, 1 for 3x3, 2 for 5x5, etc. The maximum allowed by the default chunkloading settings is 5x5, edit config/forgeChunkLoading.cfg to change those")
public static int chunkLoadingRadius = 0;

@Description(category = "Chunky Turtle", comment = "The amount of extra fuel used by a chunky turtle for movement")
public static int chunkyMovementPenalty = 1;

@Description(category = "Chunky Turtle", comment = "It will only be active if the chunkloading radius is 0. EXPERIMENTAL: This will make turtles load extra chunks when near boundaries to allow for them to traverse between chunk boundaries for 1x1 radius")
public static boolean aggressiveChunkLoading = true;
public static int chunkLoadingRadius = 1;

@Description(category = "Interactive Sorter", comment = ENABLE_CONFIG_MESSAGE)
public static boolean enableInteractiveSorter = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,48 @@
import net.minecraft.util.IIcon;

public class TurtleChunkLoader implements ITurtleUpgrade {

@Override
public int getUpgradeID() {
return Reference.CHUNK_LOADER_UPGRADE;
}

@Override
public String getUnlocalisedAdjective() {
return "peripheralsplusplus.turtleUpgrade.loader";
}

@Override
public TurtleUpgradeType getType() {
return TurtleUpgradeType.Peripheral;
}

@Override
public ItemStack getCraftingItem() {
return new ItemStack(ModItems.chunkLoaderUpgrade);
}

@Override
public IPeripheral createPeripheral(ITurtleAccess turtle, TurtleSide side) {
return new PeripheralChunkLoader(turtle);
}

@Override
public TurtleCommandResult useTool(ITurtleAccess turtle, TurtleSide side, TurtleVerb verb, int direction) {
return null;
}

@Override
public IIcon getIcon(ITurtleAccess turtle, TurtleSide side) {
return ModBlocks.dummyBlock.getIcon(0, 5);
}

@Override
public void update(ITurtleAccess turtle, TurtleSide side) {
IPeripheral peripheral = turtle.getPeripheral(side);
if (peripheral instanceof PeripheralChunkLoader)
((PeripheralChunkLoader) peripheral).update();
if (peripheral instanceof PeripheralChunkLoader) {
PeripheralChunkLoader loader = (PeripheralChunkLoader) peripheral;
loader.update();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.austinv11.peripheralsplusplus.turtles.peripherals;

import com.austinv11.peripheralsplusplus.PeripheralsPlusPlus;
import com.austinv11.peripheralsplusplus.reference.Config;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,200 +2,103 @@

import com.austinv11.peripheralsplusplus.PeripheralsPlusPlus;
import com.austinv11.peripheralsplusplus.reference.Config;
import com.austinv11.peripheralsplusplus.utils.ReflectionHelper;
import com.austinv11.peripheralsplusplus.utils.TurtleUtil;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChunkCoordinates;

import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeChunkManager;

import java.util.LinkedList;
import java.util.ArrayList;
import java.util.List;

public class PeripheralChunkLoader extends MountedPeripheral {

private ITurtleAccess turtle;
private boolean ticketCreated = false;
private ForgeChunkManager.Ticket ticket;
private IComputerAccess computer;
private ChunkCoordinates oldPos;
private int oldChunkX;
private int oldChunkZ;

private boolean attached = false;

private ChunkCoordIntPair pos;

public PeripheralChunkLoader(ITurtleAccess turtle) {
this.turtle = turtle;
this.pos = new ChunkCoordIntPair(turtle.getPosition().posX >> 4, turtle.getPosition().posZ >> 4);
}

@Override
public void attach(IComputerAccess computer) {
super.attach(computer);
PeripheralsPlusPlus.LOGGER.info("Peripheral Attached");
attached = true;
}

public void update() {
if (attached && !turtle.getWorld().isRemote) {
if (ticket == null || posChanged()) {
this.pos = new ChunkCoordIntPair(turtle.getPosition().posX >> 4, turtle.getPosition().posZ >> 4);
updateTicket();
}
}
}

@Override
public void detach(IComputerAccess computer) {
super.detach(computer);
PeripheralsPlusPlus.LOGGER.info("Peripheral Detached");
ForgeChunkManager.releaseTicket(ticket);
ticket = null;
}

public void updateTicket() {
ForgeChunkManager.releaseTicket(ticket);
ticket = ForgeChunkManager.requestTicket(PeripheralsPlusPlus.instance, turtle.getWorld(), ForgeChunkManager.Type.NORMAL);
for (ChunkCoordIntPair coordIntPair : getChunksInRadius(Config.chunkLoadingRadius)) {
ForgeChunkManager.forceChunk(ticket, coordIntPair);
}
PeripheralsPlusPlus.LOGGER.info("Ticked Updated");
}

public ArrayList<ChunkCoordIntPair> getChunksInRadius(int radius) {
ArrayList<ChunkCoordIntPair> chunkList = new ArrayList<ChunkCoordIntPair>();
for (int chunkX = pos.chunkXPos - radius; chunkX <= pos.chunkXPos + radius; chunkX++) {
for (int chunkZ = pos.chunkZPos - radius; chunkZ <= pos.chunkZPos + radius; chunkZ++) {
chunkList.add(new ChunkCoordIntPair(chunkX, chunkZ));
}
}
return chunkList;
}

public boolean posChanged() {
return !(new ChunkCoordIntPair(turtle.getPosition().posX >> 4, turtle.getPosition().posZ >> 4)).equals(pos);
}

@Override
public String getType() {
return "chunkLoader";
}

@Override
public String[] getMethodNames() {
return new String[0];
}

@Override
public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws LuaException, InterruptedException {
return new Object[0];
}

@Override
public void attach(IComputerAccess computer) {
this.computer = computer;
}

@Override
public void detach(IComputerAccess computer) {
if (ticket != null)
ForgeChunkManager.releaseTicket(ticket);
}


@Override
public boolean equals(IPeripheral other) {
return false;
return (this == other);
}

public void update() {
if (Config.enableChunkyTurtle) {
if (turtle.getWorld().isRemote)
return;

ChunkCoordinates pos = turtle.getPosition();

if (!ticketCreated) {
ticketCreated = true;
ticket = ForgeChunkManager.requestTicket(PeripheralsPlusPlus.instance, turtle.getWorld(), ForgeChunkManager.Type.NORMAL);
if (ticket == null) {
PeripheralsPlusPlus.LOGGER.warn("Chunk loading limit exceeded, not chunkloading turtle "+(computer == null ? "[unknown]" : computer.getID())+" at ("+pos.posX+","+pos.posY+","+pos.posZ+")!");
return;
}

int width = (Config.chunkLoadingRadius*2)+1+(Config.aggressiveChunkLoading && Config.chunkLoadingRadius == 0 ? 2 : 0);//The extra 2 is for another possible 2 chunks loaded
ticket.setChunkListDepth(width*width);

} else if (pos.posX != oldPos.posX || pos.posY != oldPos.posY || pos.posZ != oldPos.posZ) {
updatePos();
turtle.consumeFuel(Config.chunkyMovementPenalty);
if (ticket == null) {
PeripheralsPlusPlus.LOGGER.warn("Null ticket when moving chunkloaded turtle "+(computer == null ? "[unknown]" : computer.getID())+" at ("+pos.posX+","+pos.posY+","+pos.posZ+")!");
} else {
ForgeChunkManager.releaseTicket(ticket);
ticketCreated = false;
}
}

oldPos = pos;
}
}

private void updatePos() {
ChunkCoordinates pos = turtle.getPosition();
if (ticket != null) {
NBTTagCompound modData = ticket.getModData();
modData.setInteger("turtleX", pos.posX);
modData.setInteger("turtleY", pos.posY);
modData.setInteger("turtleZ", pos.posZ);

int chunkX = pos.posX >> 4;
int chunkZ = pos.posZ >> 4;

if (oldChunkX != chunkX || oldChunkZ != chunkZ) {
int radius = Config.chunkLoadingRadius;
for (int cx = chunkX-radius; cx <= chunkX+radius; cx++) {
for (int cz = chunkZ-radius; cz <= chunkZ+radius; cz++) {
ForgeChunkManager.forceChunk(ticket, new ChunkCoordIntPair(cx, cz));
}
}

oldChunkX = chunkX;
oldChunkZ = chunkZ;
}

if (Config.aggressiveChunkLoading && Config.chunkLoadingRadius == 0) {
if (chunkX != (pos.posX+1) >> 4) {
ForgeChunkManager.forceChunk(ticket, new ChunkCoordIntPair((pos.posX+1) >> 4, chunkZ));
} else if (chunkX != (pos.posX-1) >> 4) {
ForgeChunkManager.forceChunk(ticket, new ChunkCoordIntPair((pos.posX-1) >> 4, chunkZ));
}
if (chunkZ != (pos.posZ+1) >> 4) {
ForgeChunkManager.forceChunk(ticket, new ChunkCoordIntPair(chunkX, (pos.posZ+1) >> 4));
} else if (chunkZ != (pos.posZ-1) >> 4) {
ForgeChunkManager.forceChunk(ticket, new ChunkCoordIntPair(chunkX, (pos.posZ-1) >> 4));
}
}
}
}

public static class TurtleChunkLoadingCallback implements ForgeChunkManager.OrderedLoadingCallback {


public static class LoaderHandler implements ForgeChunkManager.LoadingCallback {
@Override
public void ticketsLoaded(List<ForgeChunkManager.Ticket> tickets, World world) {
for (ForgeChunkManager.Ticket ticket : tickets) {
int x = ticket.getModData().getInteger("turtleX");
int y = ticket.getModData().getInteger("turtleY");
int z = ticket.getModData().getInteger("turtleZ");

TileEntity te = world.getTileEntity(x, y, z);
ITurtleAccess turtle = null;
try {
if (te != null)
turtle = ReflectionHelper.getTurtle(te);
} catch (Exception e) {
e.printStackTrace();
}
if (turtle != null) {
ForgeChunkManager.forceChunk(ticket, new ChunkCoordIntPair(x >> 4, z >> 4));

PeripheralChunkLoader loader = TurtleUtil.getPeripheral((ITurtleAccess) te, PeripheralChunkLoader.class);
if (loader != null)
loader.ticketCreated = true;
}
}
}

@Override
public List<ForgeChunkManager.Ticket> ticketsLoaded(List<ForgeChunkManager.Ticket> tickets, World world, int maxTicketCount) {
List<ForgeChunkManager.Ticket> ret = new LinkedList<ForgeChunkManager.Ticket>();
List<ChunkCoordinates> known = new LinkedList<ChunkCoordinates>();

for (ForgeChunkManager.Ticket ticket : tickets) {
int x = ticket.getModData().getInteger("turtleX");
int y = ticket.getModData().getInteger("turtleY");
int z = ticket.getModData().getInteger("turtleZ");

ChunkCoordinates coords = new ChunkCoordinates(x, y, z);
if (known.contains(coords))
continue;
else
known.add(coords);

TileEntity te = world.getTileEntity(x, y, z);
ITurtleAccess turtle = null;
try {
if (te != null)
turtle = ReflectionHelper.getTurtle(te);
} catch (Exception e) {
e.printStackTrace();
}
if (turtle != null && TurtleUtil.getPeripheral((ITurtleAccess)te, PeripheralChunkLoader.class) != null) {
ret.add(ticket);
}
}

int removed = tickets.size() - known.size();
if (removed > 0)
PeripheralsPlusPlus.LOGGER.info("Removed "+removed+" bugged duplicate chunk loading tickets from world "+world.provider.dimensionId);

return ret;

}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.austinv11.peripheralsplusplus.turtles.peripherals;

import com.austinv11.peripheralsplusplus.PeripheralsPlusPlus;
import com.austinv11.peripheralsplusplus.reference.Config;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
Expand Down

0 comments on commit 5b89e7d

Please sign in to comment.