From 58f5f4da8be3f3fdc20d71c60cc0fb8853c1aba0 Mon Sep 17 00:00:00 2001 From: Guillem George Date: Sat, 7 Feb 2026 16:01:37 +0100 Subject: [PATCH] =?UTF-8?q?Et=20voil=C3=A0=20TOUTES=20les=20commandes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .factorypath | 14 ++++ .settings/org.eclipse.core.resources.prefs | 3 + .settings/org.eclipse.jdt.apt.core.prefs | 4 ++ .settings/org.eclipse.jdt.core.prefs | 9 +++ .settings/org.eclipse.m2e.core.prefs | 4 ++ src/main/java/com/epita/creeps/AsyncExec.java | 23 ++++--- src/main/java/com/epita/creeps/Program.java | 23 +++++-- .../epita/creeps/ServerReponseException.java | 7 ++ .../com/epita/creeps/commands/Basics.java | 21 ++++-- .../java/com/epita/creeps/units/Building.java | 14 ++++ .../java/com/epita/creeps/units/Citizen.java | 50 ++++++++++---- .../java/com/epita/creeps/units/Unit.java | 69 ++++++++++++++++++- 12 files changed, 205 insertions(+), 36 deletions(-) create mode 100644 .factorypath create mode 100644 .settings/org.eclipse.core.resources.prefs create mode 100644 .settings/org.eclipse.jdt.apt.core.prefs create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 src/main/java/com/epita/creeps/ServerReponseException.java create mode 100644 src/main/java/com/epita/creeps/units/Building.java diff --git a/.factorypath b/.factorypath new file mode 100644 index 0000000..41be359 --- /dev/null +++ b/.factorypath @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..e9441bb --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.apt.core.prefs b/.settings/org.eclipse.jdt.apt.core.prefs new file mode 100644 index 0000000..dfa4f3a --- /dev/null +++ b/.settings/org.eclipse.jdt.apt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.apt.aptEnabled=true +org.eclipse.jdt.apt.genSrcDir=target/generated-sources/annotations +org.eclipse.jdt.apt.genTestSrcDir=target/generated-test-sources/test-annotations diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..8f693c0 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.processAnnotations=enabled +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=21 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/src/main/java/com/epita/creeps/AsyncExec.java b/src/main/java/com/epita/creeps/AsyncExec.java index 7a5034f..fd36f47 100644 --- a/src/main/java/com/epita/creeps/AsyncExec.java +++ b/src/main/java/com/epita/creeps/AsyncExec.java @@ -1,14 +1,12 @@ package com.epita.creeps; -import com.epita.creeps.given.vo.report.Report; -import com.epita.creeps.given.vo.response.CommandResponse; -import lombok.AllArgsConstructor; + +import kong.unirest.core.HttpResponse; +import kong.unirest.core.JsonNode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import java.net.http.HttpResponse; -import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -20,18 +18,23 @@ public class AsyncExec { @Getter @Setter - private static long ticksPerSecond = 1; - private CompletableFuture task; + private static float ticksPerSecond = 1; +// private CompletableFuture task; + public static long ticksToTime(long ticks) { + return Math.ceilDiv(ticks, (long)Math.ceil(ticksPerSecond)); + } public static CompletableFuture asyncExec(Supplier supplier, long time) { return CompletableFuture.supplyAsync(supplier).thenApplyAsync(x -> x, - CompletableFuture.delayedExecutor(time/ticksPerSecond + 1, TimeUnit.SECONDS)); + CompletableFuture.delayedExecutor(ticksToTime(time), TimeUnit.SECONDS)); } public static CompletableFuture thenAsyncExec(CompletableFuture base, Function f, long time) { - return base.thenApplyAsync(f, CompletableFuture.delayedExecutor(time/ticksPerSecond + 1, TimeUnit.SECONDS)); + return base.thenApplyAsync(f, CompletableFuture.delayedExecutor(time, TimeUnit.SECONDS)); } + public static void justWait(long time) { - CompletableFuture.supplyAsync(() -> 0, CompletableFuture.delayedExecutor(time/ticksPerSecond + 1, TimeUnit.SECONDS)).join(); + CompletableFuture.supplyAsync(() -> 0, CompletableFuture.delayedExecutor(time, TimeUnit.SECONDS)).join(); } + } diff --git a/src/main/java/com/epita/creeps/Program.java b/src/main/java/com/epita/creeps/Program.java index 8fee7f0..02fb30c 100644 --- a/src/main/java/com/epita/creeps/Program.java +++ b/src/main/java/com/epita/creeps/Program.java @@ -37,10 +37,9 @@ public class Program { // Classes logger = LoggerFactory.getLogger(Program.class); - Basics basics = new Basics(logger, srvUrl); logger.info("Initializing"); + Basics.setSrvUrl(srvUrl); Citizen.srvUrl = srvUrl; - Citizen.logger = logger; logger.debug("Using server " + srvUrl + " with player " + login); if (default_values) @@ -58,19 +57,31 @@ public class Program { // Create account and get init infos logger.info("Creating account"); - InitResponse initResponse = basics.connectAccount(login); + InitResponse initResponse = Basics.connectAccount(login); login = initResponse.login; // Just in case AsyncExec.setTicksPerSecond((long)initResponse.setup.ticksPerSeconds); Citizen citizen1 = new Citizen(login, initResponse.citizen1Id); Citizen citizen2 = new Citizen(login, initResponse.citizen2Id); - while (true) { + for(int i = 0; i < 3; i++) { citizen1.move(Direction.RIGHT); citizen2.move(Direction.UP); - CommandResponse citizen1_resp = citizen1.waitFinished(); - CommandResponse citizen2_resp = citizen2.waitFinished(); + citizen1.waitFinished(); + citizen2.waitFinished(); + +// logger.debug("Received actions responses"); +// logger.debug("citizen1.error: " + citizen1_resp.error); +// logger.debug("citizen2.error: " + citizen2_resp.error); + } + + for(int i = 0; i < 3; i++) { + citizen1.move(Direction.LEFT); + citizen2.move(Direction.DOWN); + + citizen1.waitFinished(); + citizen2.waitFinished(); // logger.debug("Received actions responses"); // logger.debug("citizen1.error: " + citizen1_resp.error); diff --git a/src/main/java/com/epita/creeps/ServerReponseException.java b/src/main/java/com/epita/creeps/ServerReponseException.java new file mode 100644 index 0000000..5757612 --- /dev/null +++ b/src/main/java/com/epita/creeps/ServerReponseException.java @@ -0,0 +1,7 @@ +package com.epita.creeps; + +public class ServerReponseException extends RuntimeException { + public ServerReponseException(String message) { + super(message); + } +} diff --git a/src/main/java/com/epita/creeps/commands/Basics.java b/src/main/java/com/epita/creeps/commands/Basics.java index 740fd94..bae31e7 100644 --- a/src/main/java/com/epita/creeps/commands/Basics.java +++ b/src/main/java/com/epita/creeps/commands/Basics.java @@ -1,7 +1,9 @@ package com.epita.creeps.commands; import com.epita.creeps.AsyncExec; +import com.epita.creeps.given.exception.NoReportException; import com.epita.creeps.given.json.Json; +import com.epita.creeps.given.vo.report.Report; import com.epita.creeps.given.vo.response.InitResponse; import kong.unirest.core.HttpResponse; import kong.unirest.core.JsonNode; @@ -10,7 +12,9 @@ import kong.unirest.core.UnirestException; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.Setter; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.concurrent.CompletableFuture; @@ -18,10 +22,11 @@ import java.util.concurrent.CompletableFuture; @Getter public class Basics { - private Logger logger; - private String srvUrl; + private static final Logger logger = LoggerFactory.getLogger(Basics.class); + @Getter @Setter + private static String srvUrl; - public InitResponse connectAccount(String login) { + public static InitResponse connectAccount(String login) { try { CompletableFuture> resp = AsyncExec.asyncExec(() -> Unirest.post(srvUrl + "/init/" + login).asJson(), 0); HttpResponse response = (HttpResponse) resp.join(); @@ -38,13 +43,19 @@ public class Basics { } } - public void getReport (String reportId) { + // Asks the server for a certain report + public static Report getReport (String reportId) { HttpResponse response; try { response = Unirest.get(srvUrl + "/report/" + reportId).asJson(); - logger.debug(response.getBody().toPrettyString()); + logger.debug("Got report: " + response.getBody().toPrettyString()); + return Json.parseReport(response.getBody().toString()); } catch (UnirestException e) { logger.error("Could not retrieve report"); + throw new RuntimeException(e); + } catch (NoReportException e) { + logger.error("Could not parse report: not a report"); + throw new RuntimeException(e); } } diff --git a/src/main/java/com/epita/creeps/units/Building.java b/src/main/java/com/epita/creeps/units/Building.java new file mode 100644 index 0000000..2ceebd7 --- /dev/null +++ b/src/main/java/com/epita/creeps/units/Building.java @@ -0,0 +1,14 @@ +package com.epita.creeps.units; + +public enum Building { + TOWNHALL("town-hall"), + HOUSEHOLD("household"), + SAWMILL("sawmill"), + SMELTERY("smeltery"), + ROAD("road"); + + public final String name; + private Building(final String building) { + this.name = building; + } +} diff --git a/src/main/java/com/epita/creeps/units/Citizen.java b/src/main/java/com/epita/creeps/units/Citizen.java index 9dbf319..67d62f8 100644 --- a/src/main/java/com/epita/creeps/units/Citizen.java +++ b/src/main/java/com/epita/creeps/units/Citizen.java @@ -1,13 +1,21 @@ package com.epita.creeps.units; import com.epita.creeps.AsyncExec; +import com.epita.creeps.ServerReponseException; +import com.epita.creeps.commands.Basics; +import com.epita.creeps.given.exception.NoReportException; import com.epita.creeps.given.json.Json; import com.epita.creeps.given.vo.geometry.Direction; +import com.epita.creeps.given.vo.parameter.MessageParameter; +import com.epita.creeps.given.vo.report.MoveReport; +import com.epita.creeps.given.vo.report.Report; import com.epita.creeps.given.vo.response.CommandResponse; import kong.unirest.core.HttpResponse; import kong.unirest.core.JsonNode; import kong.unirest.core.Unirest; +import java.util.concurrent.CompletableFuture; + public class Citizen extends Unit { @@ -16,20 +24,36 @@ public class Citizen extends Unit { } public void move(Direction direction) { - pendingAction = AsyncExec.asyncExec(() -> Unirest.post(command_uri + "move:"+direction.direction).asJson(), 2) - .thenApplyAsync( x -> x ); + sendAction("move:"+direction.direction, 2); + } + public void observe() { + sendAction("observe", 1); + } + public void gather() { + sendAction("gather", 4); + } + public void unload() { + sendAction("unload", 3); + } + public void farm() { + sendAction("farm", 10); + } + public void build(Building building) { + sendAction("build:" + building.name, 20); + } + public void spawn(String unit) { + sendAction("spawn:" + unit, 6); + } + public void refine(String resource) { + sendAction("refine:" + resource, 8); + } + public void sendMessage(String receiver, String message) { + MessageParameter mp = new MessageParameter(receiver, message); + sendActionWithBody("message:send", Json.serialize(mp), 1); + } + public void fetchMessages() { + sendAction("message:fetch", 1); } - public CommandResponse waitFinished() { - if (pendingAction == null) { - logger.warn("Tried to wait a citizen with no pending action"); - return null; - } - JsonNode response = ((HttpResponse) pendingAction.join()).getBody(); - return Json.parse(response.toString(), CommandResponse.class); - } - public void noop() { -// AsyncExec.asyncExec() - } } diff --git a/src/main/java/com/epita/creeps/units/Unit.java b/src/main/java/com/epita/creeps/units/Unit.java index b163567..674f0e6 100644 --- a/src/main/java/com/epita/creeps/units/Unit.java +++ b/src/main/java/com/epita/creeps/units/Unit.java @@ -1,8 +1,16 @@ package com.epita.creeps.units; +import com.epita.creeps.AsyncExec; +import com.epita.creeps.ServerReponseException; +import com.epita.creeps.commands.Basics; +import com.epita.creeps.given.json.Json; +import com.epita.creeps.given.vo.report.Report; +import com.epita.creeps.given.vo.response.CommandResponse; import kong.unirest.core.HttpResponse; import kong.unirest.core.JsonNode; +import kong.unirest.core.Unirest; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.concurrent.CompletableFuture; @@ -10,14 +18,71 @@ public abstract class Unit { protected final String id; protected final String command_uri; protected CompletableFuture> pendingAction; + protected CompletableFuture pendingReport; public static String srvUrl; - public static Logger logger; + public static final Logger logger = LoggerFactory.getLogger(Unit.class); public Unit(String login, String id) { - if (srvUrl == null || logger == null) { + if (srvUrl == null) { throw new RuntimeException("Tried to create a citizen without properly initializing static fields"); } this.id = id; command_uri = srvUrl + "/command/" + login + "/" + id + "/"; } + + // Sends a specific action to the server using it's HTTPS string representation + // Sets pending action accordingly and asks for a report after `delay` ticks + public void sendActionWithBody(String actionCode, String body, long delay) { + // Move + pendingAction = AsyncExec.asyncExec(() -> Unirest.post(command_uri + actionCode).asJson(), delay) + .thenApplyAsync( x -> x ); + // Get report + pendingReport = getCommandReport(); + } + + // Just sends an action with an empty body + public void sendAction(String actionCode, long delay) { + sendActionWithBody(actionCode, "{}", delay); + } + + public void upgrade() { + sendAction("upgrade", 1); + } + public void noop() { + sendAction("noop", 1); + } + + /* + * @return true if action succeeded, false otherwise + */ + public boolean waitFinished() { + if (pendingAction == null || pendingReport == null) { + logger.warn("Tried to wait a citizen with no pending action or report"); + return false; + } + Report r = pendingReport.join(); + if (r == null) { + logger.warn("Invalid report received: null value"); + return false; + } + logger.debug("Got report: " + r); + + return r.errorCode != null; + } + + + // Retrieves the report of the current pending action from the server + private CompletableFuture getCommandReport() { + if (pendingAction == null) { + logger.warn("Tried to retrieve report but there's no pending action"); + return null; + } + return AsyncExec.thenAsyncExec(pendingAction, x -> { + CommandResponse cr = Json.parse(x.getBody().toString(), CommandResponse.class); + if (cr.error != null) + throw new ServerReponseException("Error retrieving the report id"); + String reportId = cr.reportId; + return Basics.getReport(reportId); + }, 0); + } }