More work on teleporters, implemented chunkloading

This commit is contained in:
Aidan C. Brady 2015-03-12 22:55:37 -05:00
parent 9c21621c06
commit f9c10d9012
11 changed files with 332 additions and 135 deletions

View file

@ -1,6 +1,7 @@
package mekanism.api;
import net.minecraft.entity.Entity;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
@ -75,6 +76,15 @@ public class Chunk3D
return world.getChunkFromChunkCoords(xCoord, zCoord);
}
/**
* Returns this Chunk3D in the Minecraft-based ChunkCoordIntPair format.
* @return this Chunk3D as a ChunkCoordIntPair
*/
public ChunkCoordIntPair toPair()
{
return new ChunkCoordIntPair(xCoord, zCoord);
}
@Override
public Coord4D clone()
{

View file

@ -5,8 +5,10 @@ import java.util.List;
import mekanism.api.EnumColor;
import mekanism.api.MekanismConfig.general;
import mekanism.common.frequency.Frequency;
import mekanism.common.frequency.FrequencyManager;
import mekanism.common.tile.TileEntityTeleporter;
import mekanism.common.util.MekanismUtils;
import net.minecraft.command.CommandBase;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.player.EntityPlayer;
@ -52,18 +54,32 @@ public class CommandMekanism extends CommandBase
sender.addChatMessage(new ChatComponentText(EnumColor.GREY + " *Recent News: " + EnumColor.INDIGO + Mekanism.recentNews));
sender.addChatMessage(new ChatComponentText(EnumColor.GREY + "------------- " + EnumColor.DARK_BLUE + "[=======]" + EnumColor.GREY + " -------------"));
}
else if(params.length == 1)
else if(params.length >= 1)
{
if(params[0].equalsIgnoreCase("help"))
{
sender.addChatMessage(new ChatComponentText(EnumColor.GREY + "------------- " + EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " -------------"));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk" + EnumColor.GREY + " -- displays the main page."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk help" + EnumColor.GREY + " -- displays this guide."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk version" + EnumColor.GREY + " -- displays the version number."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk latest" + EnumColor.GREY + " -- displays the latest version number."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk news" + EnumColor.GREY + " -- displays most recent recent news."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk debug" + EnumColor.GREY + " -- toggles Mekanism's debug mode."));
sender.addChatMessage(new ChatComponentText(EnumColor.GREY + "------------- " + EnumColor.DARK_BLUE + "[=======]" + EnumColor.GREY + " -------------"));
if(params.length == 1)
{
sender.addChatMessage(new ChatComponentText(EnumColor.GREY + "------------- " + EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " -------------"));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk" + EnumColor.GREY + " -- displays the main page."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk help" + EnumColor.GREY + " -- displays this guide."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk version" + EnumColor.GREY + " -- displays the version number."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk latest" + EnumColor.GREY + " -- displays the latest version number."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk news" + EnumColor.GREY + " -- displays most recent recent news."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk debug" + EnumColor.GREY + " -- toggles Mekanism's debug mode."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk teleporter" + EnumColor.GREY + " -- provides information on teleporters."));
sender.addChatMessage(new ChatComponentText(EnumColor.GREY + "------------- " + EnumColor.DARK_BLUE + "[=======]" + EnumColor.GREY + " -------------"));
}
else if(params[1].equalsIgnoreCase("teleporter"))
{
sender.addChatMessage(new ChatComponentText(EnumColor.GREY + "------------- " + EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " -------------"));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk teleporter freq list" + EnumColor.GREY + " -- displays a list of the public frequencies."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk teleporter freq list [user]" + EnumColor.GREY + " -- displays a list of a certain user's private frequencies."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk teleporter freq delete [freq]" + EnumColor.GREY + " -- removes a frequency from the public list."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk teleporter freq delete [user] [freq]" + EnumColor.GREY + " -- removes a freqency from a certain user's private list."));
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " /mk teleporter freq deleteAll [user]" + EnumColor.GREY + " -- removes all frequencies owned by a certain user."));
sender.addChatMessage(new ChatComponentText(EnumColor.GREY + "------------- " + EnumColor.DARK_BLUE + "[=======]" + EnumColor.GREY + " -------------"));
}
}
else if(params[0].equalsIgnoreCase("version"))
{
@ -86,6 +102,96 @@ public class CommandMekanism extends CommandBase
{
sender.addChatMessage(new ChatComponentText(EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " The latest version for this mod is " + EnumColor.DARK_GREY + Mekanism.latestVersionNumber + EnumColor.GREY + "."));
}
else if(params[0].equalsIgnoreCase("teleporter"))
{
if(params.length == 2)
{
sender.addChatMessage(new ChatComponentText(EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " Invalid parameters."));
}
else if(params[1].equalsIgnoreCase("freq") || params[1].equalsIgnoreCase("frequencies"))
{
if(params[2].equalsIgnoreCase("list"))
{
sender.addChatMessage(new ChatComponentText(EnumColor.GREY + "------------- " + EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " -------------"));
if(params.length == 3)
{
for(Frequency freq : Mekanism.publicTeleporters.getFrequencies())
{
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " - " + freq.name + EnumColor.GREY + " (" + freq.owner + ")"));
}
}
else {
FrequencyManager manager = TileEntityTeleporter.loadManager(params[3].trim(), sender.getEntityWorld());
if(manager != null)
{
for(Frequency freq : manager.getFrequencies())
{
sender.addChatMessage(new ChatComponentText(EnumColor.INDIGO + " - " + freq.name + EnumColor.GREY + " (" + freq.owner + ")"));
}
}
else {
sender.addChatMessage(new ChatComponentText(EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " User profile doesn't exist."));
}
}
sender.addChatMessage(new ChatComponentText(EnumColor.GREY + "------------- " + EnumColor.DARK_BLUE + "[=======]" + EnumColor.GREY + " -------------"));
}
else if(params[2].equalsIgnoreCase("delete"))
{
if(params.length == 4)
{
if(Mekanism.publicTeleporters.containsFrequency(params[3].trim()))
{
Mekanism.publicTeleporters.remove(params[3].trim());
sender.addChatMessage(new ChatComponentText(EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " Successfully removed frequency."));
}
else {
sender.addChatMessage(new ChatComponentText(EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " No such frequency found."));
}
}
else if(params.length == 5)
{
FrequencyManager manager = TileEntityTeleporter.loadManager(params[3].trim(), sender.getEntityWorld());
if(manager != null)
{
if(manager.containsFrequency(params[4].trim()))
{
manager.remove(params[4].trim());
sender.addChatMessage(new ChatComponentText(EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " Successfully removed frequency."));
}
else {
sender.addChatMessage(new ChatComponentText(EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " No such frequency found."));
}
}
else {
sender.addChatMessage(new ChatComponentText(EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " User profile doesn't exist."));
}
}
}
else if(params[2].equalsIgnoreCase("deleteAll"))
{
if(params.length == 4)
{
String owner = params[3].trim();
FrequencyManager manager = TileEntityTeleporter.loadManager(owner, sender.getEntityWorld());
if(manager != null)
{
int amount = Mekanism.publicTeleporters.removeAll(owner);
amount += manager.removeAll(owner);
sender.addChatMessage(new ChatComponentText(EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " Successfully removed " + amount + " frequencies."));
}
else {
sender.addChatMessage(new ChatComponentText(EnumColor.DARK_BLUE + "[Mekanism]" + EnumColor.GREY + " User profile doesn't exist."));
}
}
}
}
}
else if(params[0].equalsIgnoreCase("debug"))
{
Mekanism.debug = !Mekanism.debug;

View file

@ -37,6 +37,7 @@ import mekanism.common.base.IChunkLoadHandler;
import mekanism.common.base.IFactory.RecipeType;
import mekanism.common.base.IModule;
import mekanism.common.block.BlockMachine.MachineType;
import mekanism.common.chunkloading.ChunkManager;
import mekanism.common.content.boiler.BoilerManager;
import mekanism.common.content.boiler.SynchronizedBoilerData;
import mekanism.common.content.matrix.MatrixCache;
@ -92,6 +93,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.biome.WorldChunkManager;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.event.world.ChunkDataEvent;
@ -1156,6 +1158,9 @@ public class Mekanism
//Get data from server.
new ThreadGetData();
//Register with ForgeChunkManager
ForgeChunkManager.setForcedChunkLoadingCallback(this, new ChunkManager());
//Register to receive subscribed events
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);

View file

@ -780,6 +780,20 @@ public class BlockBasic extends Block implements IBlockCTM, ICustomBlockIcon
return false;
}
}
@Override
public void onBlockAdded(World world, int x, int y, int z)
{
TileEntity tileEntity = world.getTileEntity(x, y, z);
if(!world.isRemote)
{
if(tileEntity instanceof TileEntityBasicBlock)
{
((TileEntityBasicBlock)tileEntity).onAdded();
}
}
}
@Override
public TileEntity createTileEntity(World world, int metadata)

View file

@ -980,6 +980,20 @@ public class BlockMachine extends BlockContainer implements ISpecialBounds, IPer
return itemStack;
}
@Override
public void onBlockAdded(World world, int x, int y, int z)
{
TileEntity tileEntity = world.getTileEntity(x, y, z);
if(!world.isRemote)
{
if(tileEntity instanceof TileEntityBasicBlock)
{
((TileEntityBasicBlock)tileEntity).onAdded();
}
}
}
public ItemStack dismantleBlock(World world, int x, int y, int z, boolean returnBlock)
{

View file

@ -0,0 +1,29 @@
package mekanism.common.chunkloading;
import java.util.List;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeChunkManager.LoadingCallback;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
public class ChunkManager implements LoadingCallback
{
@Override
public void ticketsLoaded(List<Ticket> tickets, World world)
{
for(Ticket ticket : tickets)
{
int x = ticket.getModData().getInteger("xCoord");
int y = ticket.getModData().getInteger("yCoord");
int z = ticket.getModData().getInteger("zCoord");
TileEntity tileEntity = world.getTileEntity(x, y, z);
if(tileEntity instanceof IChunkLoader)
{
((IChunkLoader)tileEntity).forceChunks(ticket);
}
}
}
}

View file

@ -0,0 +1,8 @@
package mekanism.common.chunkloading;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
public interface IChunkLoader
{
public void forceChunks(Ticket ticket);
}

View file

@ -1,117 +0,0 @@
package mekanism.common.classloading;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import mekanism.common.Mekanism;
public class ClassEnumerator
{
private static Class<?> loadClass(String className)
{
try {
return Class.forName(className);
} catch(ClassNotFoundException e) {
throw new RuntimeException("Unexpected ClassNotFoundException loading class '" + className + "'");
}
}
private static void processDir(File directory, String pkgname, ArrayList<Class<?>> classes)
{
String[] files = directory.list();
for(int i = 0; i < files.length; i++)
{
String fileName = files[i];
String className = null;
if(fileName.endsWith(".class"))
{
className = pkgname + '.' + fileName.substring(0, fileName.length() - 6);
}
if(className != null)
{
classes.add(loadClass(className));
}
File subdir = new File(directory, fileName);
if(subdir.isDirectory())
{
processDir(subdir, pkgname + '.' + fileName, classes);
}
}
}
private static void processJar(URL resource, String pkgname, ArrayList<Class<?>> classes)
{
String relPath = pkgname.replace('.', '/');
String resPath = resource.getPath();
String jarPath = resPath.replaceFirst("[.]jar[!].*", ".jar").replaceFirst("file:", "");
JarFile jarFile;
try {
jarFile = new JarFile(jarPath);
} catch(IOException e) {
throw new RuntimeException("Unexpected IOException reading JAR File '" + jarPath + "'", e);
}
Enumeration<JarEntry> entries = jarFile.entries();
while(entries.hasMoreElements())
{
JarEntry entry = entries.nextElement();
String entryName = entry.getName();
String className = null;
if(entryName.endsWith(".class") && entryName.startsWith(relPath) && entryName.length() > (relPath.length() + "/".length()))
{
className = entryName.replace('/', '.').replace('\\', '.').replace(".class", "");
}
if(className != null)
{
classes.add(loadClass(className));
}
}
}
public static ArrayList<Class<?>> getClassesForPackage(Package pkg)
{
ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
try {
String pkgname = pkg.getName();
String relPath = pkgname.replace('.', '/');
URL resource = ClassLoader.getSystemClassLoader().getResource(relPath);
if(resource == null)
{
throw new RuntimeException("Unexpected problem: No resource for " + relPath);
}
resource.getPath();
if(resource.toString().startsWith("jar:"))
{
processJar(resource, pkgname, classes);
}
else {
processDir(new File(resource.getPath()), pkgname, classes);
}
} catch(Exception e) {
Mekanism.logger.error("Error while loading classes in package " + pkg);
e.printStackTrace();
}
return classes;
}
}

View file

@ -82,6 +82,39 @@ public class FrequencyManager
}
}
public void remove(String name)
{
for(Iterator<Frequency> iter = getFrequencies().iterator(); iter.hasNext();)
{
Frequency iterFreq = iter.next();
if(iterFreq.name.equals(name))
{
iter.remove();
dataHandler.markDirty();
}
}
}
public int removeAll(String user)
{
int amount = 0;
for(Iterator<Frequency> iter = getFrequencies().iterator(); iter.hasNext();)
{
Frequency iterFreq = iter.next();
if(iterFreq.owner.equals(user))
{
iter.remove();
dataHandler.markDirty();
amount++;
}
}
return amount;
}
public void deactivate(Coord4D coord)
{
for(Frequency freq : frequencies)
@ -137,6 +170,25 @@ public class FrequencyManager
}
}
public static FrequencyManager loadOnly(World world, String owner, Class<? extends Frequency> freqClass)
{
FrequencyManager manager = new FrequencyManager(freqClass);
String name = manager.getName();
FrequencyDataHandler handler = (FrequencyDataHandler)world.perWorldStorage.loadData(FrequencyDataHandler.class, name);
if(handler == null)
{
return null;
}
else {
manager.dataHandler = handler;
manager.dataHandler.syncManager();
return manager;
}
}
public Set<Frequency> getFrequencies()
{
return frequencies;
@ -148,9 +200,17 @@ public class FrequencyManager
dataHandler.markDirty();
}
public boolean containsFrequency(Frequency freq)
public boolean containsFrequency(String name)
{
return frequencies.contains(freq);
for(Frequency freq : frequencies)
{
if(freq.name.equals(name))
{
return true;
}
}
return false;
}
public void writeFrequencies(ArrayList data)

View file

@ -8,12 +8,13 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
import mekanism.api.Chunk3D;
import mekanism.api.Coord4D;
import mekanism.api.EnumColor;
import mekanism.common.Mekanism;
import mekanism.common.MekanismBlocks;
import mekanism.common.PacketHandler;
import mekanism.common.block.BlockMachine.MachineType;
import mekanism.common.chunkloading.IChunkLoader;
import mekanism.common.frequency.Frequency;
import mekanism.common.frequency.FrequencyManager;
import mekanism.common.network.PacketPortalFX.PortalFXMessage;
@ -32,6 +33,9 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
import net.minecraftforge.common.ForgeChunkManager.Type;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Optional.Interface;
import cpw.mods.fml.common.Optional.Method;
@ -43,7 +47,7 @@ import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
@Interface(iface = "dan200.computercraft.api.peripheral.IPeripheral", modid = "ComputerCraft")
public class TileEntityTeleporter extends TileEntityElectricBlock implements IPeripheral
public class TileEntityTeleporter extends TileEntityElectricBlock implements IPeripheral, IChunkLoader
{
private MinecraftServer server = MinecraftServer.getServer();
@ -63,6 +67,8 @@ public class TileEntityTeleporter extends TileEntityElectricBlock implements IPe
public List<Frequency> publicCache = new ArrayList<Frequency>();
public List<Frequency> privateCache = new ArrayList<Frequency>();
public Ticket chunkTicket;
/** This teleporter's current status. */
public byte status = 0;
@ -85,6 +91,20 @@ public class TileEntityTeleporter extends TileEntityElectricBlock implements IPe
if(!worldObj.isRemote)
{
if(chunkTicket == null)
{
Ticket ticket = ForgeChunkManager.requestTicket(Mekanism.instance, worldObj, Type.NORMAL);
if(ticket != null)
{
ticket.getModData().setInteger("xCoord", xCoord);
ticket.getModData().setInteger("yCoord", yCoord);
ticket.getModData().setInteger("zCoord", zCoord);
forceChunks(ticket);
}
}
FrequencyManager manager = getManager(frequency);
if(manager != null)
@ -145,6 +165,7 @@ public class TileEntityTeleporter extends TileEntityElectricBlock implements IPe
}
FrequencyManager manager = getManager(new Frequency(name, null).setPublic(publicFreq));
manager.deactivate(Coord4D.get(this));
for(Frequency freq : manager.getFrequencies())
{
@ -187,6 +208,16 @@ public class TileEntityTeleporter extends TileEntityElectricBlock implements IPe
}
}
public static FrequencyManager loadManager(String owner, World world)
{
if(Mekanism.privateTeleporters.containsKey(owner))
{
return Mekanism.privateTeleporters.get(owner);
}
return FrequencyManager.loadOnly(world, owner, Frequency.class);
}
@Override
public void onChunkUnload()
{
@ -208,13 +239,18 @@ public class TileEntityTeleporter extends TileEntityElectricBlock implements IPe
{
super.invalidate();
if(!worldObj.isRemote && frequency != null)
if(!worldObj.isRemote)
{
FrequencyManager manager = getManager(frequency);
releaseChunks();
if(manager != null)
if(frequency != null)
{
manager.deactivate(Coord4D.get(this));
FrequencyManager manager = getManager(frequency);
if(manager != null)
{
manager.deactivate(Coord4D.get(this));
}
}
}
}
@ -679,4 +715,22 @@ public class TileEntityTeleporter extends TileEntityElectricBlock implements IPe
{
return INFINITE_EXTENT_AABB;
}
@Override
public void forceChunks(Ticket ticket)
{
releaseChunks();
chunkTicket = ticket;
ForgeChunkManager.forceChunk(chunkTicket, new Chunk3D(Coord4D.get(this)).toPair());
}
public void releaseChunks()
{
if(chunkTicket != null)
{
ForgeChunkManager.releaseTicket(chunkTicket);
chunkTicket = null;
}
}
}

View file

@ -424,6 +424,20 @@ public class BlockGenerator extends BlockContainer implements ISpecialBounds, IP
setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
}
}
@Override
public void onBlockAdded(World world, int x, int y, int z)
{
TileEntity tileEntity = world.getTileEntity(x, y, z);
if(!world.isRemote)
{
if(tileEntity instanceof TileEntityBasicBlock)
{
((TileEntityBasicBlock)tileEntity).onAdded();
}
}
}
@Override
public boolean removedByPlayer(World world, EntityPlayer player, int x, int y, int z, boolean willHarvest)