package org.pixelgaffer.turnierserver.codr.simulator;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import lombok.Getter;
import lombok.NonNull;
import org.pixelgaffer.turnierserver.codr.GameSaved;
import org.pixelgaffer.turnierserver.codr.Version;
import org.pixelgaffer.turnierserver.codr.utilities.Libraries;
import org.pixelgaffer.turnierserver.codr.utilities.Paths;
import org.pixelgaffer.turnierserver.gamelogic.GameLogic;
import org.pixelgaffer.turnierserver.gamelogic.interfaces.Frontend;
import org.pixelgaffer.turnierserver.gamelogic.interfaces.Game;
public class CodrGameImpl implements Game, Frontend
{
/**
* Lädt die GameLogic und gibt eine Instanz davon zurück.
*/
public static GameLogic<?, ?> loadGameLogic (@NonNull String game) // siehe
// Games.loadGameLogic
// im Backend
throws IOException, ReflectiveOperationException
{
File jar = new File(Paths.gameLogic(game));
// manifest lesen
JarFile jarFile = new JarFile(jar);
Manifest mf = jarFile.getManifest();
String classname = mf.getMainAttributes().getValue("Logic-Class");
String requiredLibs[] = mf.getMainAttributes().getValue("Required-Libs").split("\\s+");
jarFile.close();
// klasse laden
List<URL> urls = new ArrayList<>();
urls.add(jar.toURI().toURL());
Libraries libs = new Libraries();
for (String lib : requiredLibs)
if (!lib.isEmpty())
for (File f : libs.getLib("Java", lib))
urls.add(f.toURI().toURL());
@SuppressWarnings("resource")
URLClassLoader cl = new URLClassLoader(urls.toArray(new URL[0]));
Class<?> clazz = cl.loadClass(classname);
return (GameLogic<?, ?>)clazz.newInstance();
}
@Getter
private boolean started;
private Map<UUID, CodrAiWrapper> aiWrappers = new HashMap<>();
public CodrAiWrapper getAi (UUID uuid)
{
return aiWrappers.get(uuid);
}
@Getter
private List<CodrAiWrapper> ais = new ArrayList<>();
UUID randomUUID ()
{
UUID uuid;
do
{
uuid = UUID.randomUUID();
}
while (aiWrappers.containsKey(uuid));
return uuid;
}
@Getter
private GameLogic<?, ?> logic;
private OutputStream renderData;
public CodrGameImpl (GameSaved game, Collection<Version> opponents) throws IOException, ReflectiveOperationException
{
System.out.println("CodrGameImpl(" + game + ", " + opponents + ")");
System.out.println(game.gameType);
renderData = new FileOutputStream(Paths.gameRenderData(game));
logic = loadGameLogic(game.gameType);
for (Version v : opponents)
{
System.out.println(v);
CodrAiWrapper aiw = new CodrAiWrapper(this, randomUUID());
aiw.setIndex(ais.size());
aiw.setId(v.ai.title + "v" + v.number);
aiw.setVersion(v);
ais.add(aiw);
aiWrappers.put(aiw.getUuid(), aiw);
}
}
@Override
public Frontend getFrontend ()
{
return this;
}
@Override
public synchronized void finishGame () throws IOException
{
synchronized (renderData)
{
renderData.close();
}
for (CodrAiWrapper aiw : ais)
aiw.disconnect();
}
public void startAis (Properties p) throws IOException
{
for (CodrAiWrapper aiw : ais)
{
p.put("turnierserver.ai.uuid", aiw.getUuid().toString());
System.out.println(p);
File f = Files.createTempFile("ai", ".prop").toFile();
p.store(new FileOutputStream(f), null);
aiw.executeAi(f.getAbsolutePath());
}
}
public synchronized void aiConnected ()
{
if (!isStarted())
{
boolean start = true;
for (CodrAiWrapper aiw : ais)
{
if (!aiw.isConnected())
{
start = false;
break;
}
}
if (start)
{
System.out.println("Alle KIs verbunden, das Spiel wird gestartet");
logic.startGame(this);
started = true;
}
}
}
// Frontend iface
@Override
public int getRequestId ()
{
return 0;
}
@Override
public void sendMessage (byte[] message) throws IOException
{
synchronized (renderData)
{
renderData.write(message);
renderData.flush();
}
}
@Override
public UUID getUuid() {
return UUID.randomUUID();
}
}