package net.tacospice.stevenet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import net.tacospice.stevenet.NetworkMessages.CreateNode;
import net.tacospice.stevenet.Replicator.ReplicationType;
abstract public class ClientServer extends NetEndpoint
{
protected final HashMap<Integer, Node> nodes;
private float updateRate;
private float accumulator;
private final boolean isServer;
private float timeSinceFullUpdate;
private boolean doFullUpdate;
protected int nextPacketSequence;
private final ArrayList<Class<?>> classTypes;
public ClientServer(boolean isServer)
{
nodes = new HashMap<Integer, Node>();
setUpdateRate(10);
accumulator = 0.0f;
timeSinceFullUpdate = 0.0f;
doFullUpdate = true;
nextPacketSequence = 0;
this.isServer = isServer;
classTypes = new ArrayList<Class<?>>();
}
public void setUpdateRate(float fps)
{
updateRate = 1.0f / fps;
}
public int registerClass(Class<?> c)
{
classTypes.add(c);
return classTypes.size() - 1;
}
public int getClassId(Class<?> c)
{
for (int i = 0; i < classTypes.size(); ++i)
{
if (classTypes.get(i) == c)
return i;
}
throw new IllegalArgumentException("Class type is not registered");
}
public void update(float delta)
{
accumulator += delta;
timeSinceFullUpdate += delta;
if (timeSinceFullUpdate >= 1.0f)
{
timeSinceFullUpdate = 0.0f;
doFullUpdate = true;
}
while (accumulator >= updateRate)
{
accumulator -= updateRate;
for (Node n : nodes.values())
{
// Broadcast to clients if necessary
if (isServer && !n.wasBroadcast())
{
CreateNode cn = new CreateNode();
cn.id = n.getId();
cn.classId = n.getClassId();
cn.owner = false;
sendToAllExceptTCP(n.getOwner(), cn);
// If node has owner, send special message
if (n.getOwner() != -1)
{
cn = new CreateNode();
cn.id = n.getId();
cn.classId = n.getClassId();
cn.owner = true;
sendToTCP(n.getOwner(), cn);
}
n.broadcastDone();
}
// Send replication messages
Iterator<Replicator> repIter = n.getIterator();
int repId = 0;
while (repIter.hasNext())
{
Replicator r = repIter.next();
if (r.needSend() || r.alwaysUpdate() || doFullUpdate)
{
ReplicatorMessage message = r.getMessage(n.getId(), repId);
message.packetSequence = nextPacketSequence++;
if (isServer)
{
if (r.getReplicationType() == ReplicationType.ToProxy)
sendToAllExceptUDP(n.getOwner(), message);
else if (r.getReplicationType() == ReplicationType.ToOwner)
sendToUDP(n.getOwner(), message);
else if (r.getReplicationType() == ReplicationType.ToBoth)
sendToAllUDP(message);
// if ReplicationType.ToNeither, don't bother sending
r.markSent();
}
else if (r.getOwnerToServer() && n.getOwner() == 1)
{
sendUDP(message);
r.markSent();
}
}
++repId;
}
}
doFullUpdate = false;
}
}
public void addNode(Node n)
{
if (!n.getSetupDone())
throw new IllegalStateException("Can't add nodes that have not been set up");
nodes.put(n.getId(), n);
}
public void removeNode(Node n)
{
nodes.remove(n.getId());
}
public void clearNodes()
{
nodes.clear();
}
}