Skip to content

Instantly share code, notes, and snippets.

@mcenderdragon
Created March 5, 2018 22:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mcenderdragon/e9df9b0f4adc69a6bd488f9e9d0319cd to your computer and use it in GitHub Desktop.
Save mcenderdragon/e9df9b0f4adc69a6bd488f9e9d0319cd to your computer and use it in GitHub Desktop.
The ingame Network System
package futurepack.api.interfaces;
import futurepack.api.PacketBase;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/**
* This is needed for everything that sends a {@link futurepack.api.PacketBase}
* See {@link futurepack.common.network.NetworkManager}
*/
public interface INetworkUser
{
/**
* The World of the sender.
*/
public World getWorldObj();
/**
* the Position of the sender.
*/
public BlockPos getBlockPos();
/**
* This is called after the Packet is sent.
* @param pkt the Packet after everyone has received it.
*/
public void postPacketSend(PacketBase pkt);
}
package futurepack.api.interfaces;
import futurepack.api.PacketBase;
/**
* Implement this in your {@link net.minecraft.tileentity.TileEntity} and you will receive packets from the network. This is used for the research modules.
*/
public interface ITileNetwork
{
/**
* @return if this is a Network machine (true) or just have this Interface implemented (false)
*/
public boolean isNetworkAble();
/**
* @return if this is a wire or a Machine. (Machines are ends of the network)
*/
public boolean isWire();
/**
* Wires Dont recive packets
*/
public void onFunkPacket(PacketBase pkt);
}
package futurepack.common.network;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import futurepack.api.PacketBase;
import futurepack.api.ParentCoords;
import futurepack.api.interfaces.IBlockValidator;
import futurepack.api.interfaces.INetworkUser;
import futurepack.api.interfaces.ITileNetwork;
import futurepack.common.FPBlockSelector;
import futurepack.common.FPSelectorHelper;
import futurepack.depend.api.interfaces.IBlockSelector;
import net.minecraft.block.material.Material;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.eventhandler.EventBus;
public class NetworkManager implements Runnable
{
private static NetworkManager instance = new NetworkManager();
private static IBlockSelector selectorNetwork = new IBlockSelector()
{
@Override
public boolean isValidBlock(World w, BlockPos pos, Material m, boolean dia, ParentCoords parent)
{
if(dia)
return false;
if(w.getTileEntity(pos) instanceof ITileNetwork)
{
ITileNetwork net = (ITileNetwork) w.getTileEntity(pos);
return net.isNetworkAble();
}
return false;
}
@Override
public boolean canContinue(World w, BlockPos pos, Material m, boolean dia, ParentCoords parent)
{
ITileNetwork net = (ITileNetwork) w.getTileEntity(pos);
return net.isWire();
}
};
private static IBlockValidator selectorMachines = new IBlockValidator()
{
@Override
public boolean isValidBlock(World w, ParentCoords pos)
{
ITileNetwork net = (ITileNetwork) w.getTileEntity(pos);
return net!=null && !net.isWire();
}
};
private static HashMap<Integer,EventBus> Networks = new HashMap<Integer, EventBus>();
public static List<ITileNetwork> pingNetwork(INetworkUser user)
{
FunkPacketPing pkt = new FunkPacketPing(user.getBlockPos(), (ITileNetwork) user.getWorldObj().getTileEntity(user.getBlockPos()));
sendPacketThreaded(user, pkt);
return pkt.getReachable();
}
public static void sendPacketThreaded(INetworkUser user, PacketBase pkt)
{
instance.sendSave(user, pkt);
}
public static void sendPacketUnthreaded(INetworkUser user, PacketBase pkt)
{
instance.send(user, pkt);
}
private Thread thread;
private ArrayList<Object[]> todo = new ArrayList<Object[]>();
public NetworkManager()
{
thread = new Thread(this, "Network-Thread");
thread.setDaemon(true);
thread.start();
}
private void send(INetworkUser user, PacketBase pkt)
{
FPBlockSelector sel = FPSelectorHelper.getSelector(user.getWorldObj(), user.getBlockPos(), selectorNetwork);
Collection<ParentCoords> machines = sel.getValidBlocks(selectorMachines);
for(ParentCoords c : machines)
{
if(user.getBlockPos().equals(c))
{
continue;
}
TileEntity tile = user.getWorldObj().getTileEntity(c);
if(tile.isInvalid())
continue;
ITileNetwork net = (ITileNetwork) tile;
pkt.post(net);
}
user.postPacketSend(pkt);
}
public void sendSave(INetworkUser user, PacketBase pkt)
{
if(thread.isAlive())
{
todo.add(new Object[]{user, pkt});
synchronized (todo)
{
todo.notify();
}
}
else
{
System.err.println("Network Thread DIED");
}
}
public static void registerWirelessTile(TileEntity t)
{
EventBus wirelessNetwork = Networks.get(t.getWorld().provider.getDimension());
if(wirelessNetwork==null)
{
wirelessNetwork = new EventBus();
Networks.put(t.getWorld().provider.getDimension(), wirelessNetwork);
}
wirelessNetwork.register(t);
}
public static void unregisterWirelessTile(TileEntity t)
{
EventBus wirelessNetwork = Networks.get(t.getWorld().provider.getDimension());
if(wirelessNetwork!=null)
{
wirelessNetwork.unregister(t);
}
}
public static void sendEvent(EventWirelessFunk e, int dim)
{
Networks.get(dim).post(e);
}
@Override
public void run()
{
while(true)
{
try
{
synchronized (todo)
{
while(!todo.isEmpty())
{
Object[] next = todo.remove(0);
if(next!=null)
{
send((INetworkUser)next[0], (PacketBase)next[1]);
}
}
todo.wait();
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
package futurepack.api;
import java.util.ArrayList;
import futurepack.api.interfaces.ITileNetwork;
import net.minecraft.util.math.BlockPos;
/**
* This is the base packet sended in the Network. (Ingame)
*/
public class PacketBase
{
private BlockPos src;
private ITileNetwork sender;
private ArrayList<ITileNetwork> users = new ArrayList<ITileNetwork>();
public PacketBase(BlockPos src, ITileNetwork net)
{
this.src = src;
this.sender = net;
users.add(net);
}
/**
* This packet will be send to the <b>net</b> if it has not already received it.
*
* @param net the receiver
*/
public void post(ITileNetwork net)
{
if(!users.contains(net))
{
users.add(net);
net.onFunkPacket(this);
}
}
/**
* @return the Block Cordiants of the sender
*/
public BlockPos getSenderPosition()
{
return src;
}
/**
* @return the instance of the Sender
*/
public ITileNetwork getSender()
{
return sender;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment