mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-04-19 18:46:43 +00:00
Compare commits
240 Commits
Author | SHA1 | Date | |
---|---|---|---|
ac374f5b52 | |||
|
d01eac646f | ||
35b48ddd95 | |||
|
5a0c5b6911 | ||
a85e672eb9 | |||
053d3e35ec | |||
|
35140cc834 | ||
6a9c656e66 | |||
|
d07a59607f | ||
cd9e555e86 | |||
|
7c0187f514 | ||
ac27250f98 | |||
|
84f59a5fa2 | ||
a0193621a8 | |||
922162660f | |||
014dab49da | |||
|
4c81937edc | ||
2597b558e6 | |||
ea1ec1b1b3 | |||
8b55466e7c | |||
|
03ff2e5527 | ||
|
634af8859f | ||
|
39ca4d5143 | ||
|
5f3c34911c | ||
|
638c5b3bb3 | ||
|
50e0baa6ec | ||
|
3a35f3fdfc | ||
|
2982fcbbc1 | ||
|
fb97415ee7 | ||
|
f37ae36262 | ||
|
556b46badc | ||
|
d57f8d2970 | ||
|
629dac6ea3 | ||
|
55fdd93d9d | ||
|
2f7d2cd85a | ||
|
6e4b2358af | ||
|
f9c7f02870 | ||
|
86b331fc60 | ||
|
35b6f06687 | ||
|
bcd96be625 | ||
|
f99f327480 | ||
|
d71b3dc97c | ||
|
e378016c56 | ||
|
c50cc8c364 | ||
|
bf9cdc7b29 | ||
|
75410cc0db | ||
|
e0ed1e0e6f | ||
|
0fbd1d1a6b | ||
|
8018fb3e30 | ||
|
fb8fdac9c3 | ||
|
a3253e8e3a | ||
|
9ee754e5be | ||
|
e72e8b45c5 | ||
|
311889bc93 | ||
|
9cb2c29f0f | ||
|
f3ae97c060 | ||
|
e8033f3291 | ||
|
b19eb0568d | ||
|
9aa876df62 | ||
|
b1da29d7fb | ||
|
12f20d178a | ||
|
a030e9fc5d | ||
|
439547102f | ||
|
d5ddb8e439 | ||
|
4f4cecf60c | ||
|
a1136f9056 | ||
|
d2e7084354 | ||
|
1157bd5df5 | ||
|
0ff671713c | ||
|
2590e8ec64 | ||
|
a768cf0f4b | ||
|
7b3839f046 | ||
|
4958c3d9a0 | ||
|
f8eec652ae | ||
|
762bad758b | ||
|
3e2422775e | ||
|
993838651f | ||
|
ce8c5375ee | ||
|
91ebb51389 | ||
|
d113f635a1 | ||
|
78a9f78a54 | ||
|
4f8eb2725e | ||
|
ff4f6c23eb | ||
|
c5a34c7a3f | ||
|
1d3d441996 | ||
|
7ba46ec36e | ||
|
63cdfb22ac | ||
|
f9898f57f4 | ||
|
2548242da8 | ||
|
46d5c9b51e | ||
|
7fd1c35f7a | ||
|
0dbec1d258 | ||
|
45d3b84dd0 | ||
|
af4ddbdd89 | ||
|
84ca3acb52 | ||
|
0973548b71 | ||
|
5f95c17aed | ||
|
b361f87154 | ||
|
e4a06e79d4 | ||
|
955d61ce99 | ||
|
201d83f8d8 | ||
|
94b8ef5395 | ||
|
70eeb1442d | ||
|
bbaa338469 | ||
|
5de909cd9c | ||
|
71e88afdc9 | ||
|
ae41bd9cb9 | ||
|
de45eb1827 | ||
|
6c7a2f0a73 | ||
|
3776070689 | ||
|
54ed05b86c | ||
|
b361583252 | ||
|
04c837d692 | ||
|
aaeb18068d | ||
|
e848fd8b8a | ||
|
1435d31d36 | ||
|
950f6b6b4b | ||
|
6a9cfb3acb | ||
|
4be1bf2e8a | ||
|
e50bcdeab7 | ||
|
c8214236ab | ||
|
37b7bbff98 | ||
|
be7304aa0b | ||
|
0845438297 | ||
|
564a692c2e | ||
|
a40a0712f0 | ||
|
f89c39c756 | ||
|
a6f0ce1dfb | ||
|
2f80205b2a | ||
|
71f96f27d1 | ||
|
98402dd45b | ||
|
548d756e90 | ||
|
1a2332bc32 | ||
|
9a73b7b7d1 | ||
|
d860591cc8 | ||
|
268acda773 | ||
|
6d66e19dc5 | ||
|
40e7899cf6 | ||
|
abb92bfc75 | ||
|
becf6e5feb | ||
|
8af652482d | ||
|
205845d6af | ||
|
64193ecf7a | ||
|
a1cf279b6f | ||
|
6074238131 | ||
|
fa62c49fa8 | ||
|
a0aaee7ee7 | ||
|
96fc3ed68c | ||
|
e69111ff3c | ||
|
e7e9a3e6fb | ||
|
a73aa7c3a5 | ||
|
e8543082ce | ||
|
4b7ebd7ad6 | ||
|
c389bbc92e | ||
|
78f98c8227 | ||
|
92008e553a | ||
|
45d34c37ad | ||
|
a9cc9662f4 | ||
|
df9c466827 | ||
|
b65c57ceba | ||
|
2f74dd45fc | ||
|
07160138aa | ||
|
b6a206f3c7 | ||
|
ed1c4cff0b | ||
|
a005e2b163 | ||
|
a7bdbd2513 | ||
|
ee9eeeef55 | ||
|
4b67798180 | ||
|
be8dd14d36 | ||
|
80f45f1eb0 | ||
|
3368268924 | ||
|
4cd58c86a5 | ||
|
8d029cf621 | ||
|
10f088cb66 | ||
|
159c217d59 | ||
|
c5cb5df335 | ||
|
854863ede9 | ||
|
e98575b23f | ||
|
1a5d12a19f | ||
|
1678be25c5 | ||
|
9c41c16079 | ||
|
e97ecbe380 | ||
|
083af31b84 | ||
|
2c856aae80 | ||
|
315e33055e | ||
|
e025b6d2da | ||
|
e3a650a4fc | ||
|
113aa50d87 | ||
|
dc034d1437 | ||
|
3492e133e1 | ||
|
bd5f8573e8 | ||
|
3c5bfdb30b | ||
|
9349ae108b | ||
|
292adb5483 | ||
|
e479d89375 | ||
|
41d674d74a | ||
|
227f7ce5aa | ||
|
a091071d55 | ||
|
f1b8f3dc6d | ||
|
e62a51ee2e | ||
|
217c997788 | ||
|
ff61433c4b | ||
|
cbde2450fa | ||
|
1d780f7d9b | ||
|
cbb07891fc | ||
|
2565d3338c | ||
|
e4269b83c4 | ||
|
9cac665101 | ||
|
dc19176dc8 | ||
|
8ed192f8d0 | ||
|
d1a3cf9307 | ||
|
f8c5dac969 | ||
|
0a75cb557d | ||
|
f35e6c5a9a | ||
|
0ada6c29d4 | ||
|
156deb8f4e | ||
|
039088ac00 | ||
|
f530dafdee | ||
|
817dbcc6c4 | ||
|
62f1403cb3 | ||
|
8c6e580ea9 | ||
|
6a1519d97d | ||
|
95a14ad1ab | ||
|
187a828c79 | ||
|
ffca185fe5 | ||
|
815f3de234 | ||
|
3505a466bb | ||
|
3d10e4306b | ||
|
a285b3104e | ||
|
947deea784 | ||
|
4293fc0315 | ||
|
f1c1f8f807 | ||
|
a04207b5e0 | ||
|
46483b2bf8 | ||
|
9bb0dc9034 | ||
|
1da894959e | ||
|
7e773699b6 | ||
|
bc29c36204 | ||
|
eb3deba544 | ||
|
c7da764505 |
5
.gitattributes
vendored
Normal file
5
.gitattributes
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Server/src/main/resources/static/css/bootstrap4-neon-glow.min linguist-vendored
|
||||||
|
Server/src/main/resources/static/css/bootstrap-grid.min linguist-vendored
|
||||||
|
Server/src/main/resources/static/css/bootstrap-reboot.min linguist-vendored
|
||||||
|
Server/src/main/resources/static/js/* linguist-vendored
|
||||||
|
Server/src/main/resources/static/js/ace/* linguist-vendored
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -15,3 +15,8 @@ Server/Server.iml
|
|||||||
target/*
|
target/*
|
||||||
Server/Server.iml
|
Server/Server.iml
|
||||||
Server/src/main/java/META-INF/MANIFEST.MF
|
Server/src/main/java/META-INF/MANIFEST.MF
|
||||||
|
.settings
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
# VSCode Workspace
|
||||||
|
.vscode/
|
@ -1,7 +1,6 @@
|
|||||||
FROM alpine:3.7
|
FROM maven:3.5-jdk-8
|
||||||
RUN apk add --no-cache maven openjdk8
|
|
||||||
COPY /. /app/
|
COPY /. /app/
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN mvn package \
|
RUN mvn package
|
||||||
&& cp Server/src/main/resources/config.properties /app/
|
WORKDIR /app/target
|
||||||
CMD ["java", "-jar", "/app/target/server-1.2a.jar"]
|
CMD ["java", "-jar", "/app/target/server-1.4a.jar"]
|
@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="Spring" name="Spring">
|
||||||
|
<configuration />
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
@ -13,11 +18,40 @@
|
|||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="module" module-name="Server" />
|
<orderEntry type="module" module-name="Server" />
|
||||||
<orderEntry type="library" name="Maven: org.java-websocket:Java-WebSocket:1.3.6" level="project" />
|
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.6" level="project" />
|
||||||
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.42" level="project" />
|
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-sync:3.9.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:bson:3.9.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:2.10.1" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-core:3.9.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.1.5.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.8.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.sparkjava:spark-template-velocity:2.7.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.25" level="project" />
|
||||||
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
|
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
||||||
|
@ -7,19 +7,19 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.simon987.server</groupId>
|
<groupId>net.simon987.server</groupId>
|
||||||
<artifactId>server_root</artifactId>
|
<artifactId>server_root</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.simon987.plugincubot</groupId>
|
<groupId>net.simon987.plugincubot</groupId>
|
||||||
<artifactId>plugin-cubot</artifactId>
|
<artifactId>plugin-cubot</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.simon987.server</groupId>
|
<groupId>net.simon987.server</groupId>
|
||||||
<artifactId>server</artifactId>
|
<artifactId>server</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,56 +1,155 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import net.simon987.cubotplugin.event.CubotWalkEvent;
|
||||||
import com.mongodb.DBObject;
|
import net.simon987.cubotplugin.event.DeathEvent;
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.IServerConfiguration;
|
||||||
|
import net.simon987.server.assembly.CPU;
|
||||||
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import net.simon987.server.assembly.Memory;
|
import net.simon987.server.assembly.Memory;
|
||||||
import net.simon987.server.game.*;
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.assembly.exception.CancelledException;
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.game.item.Item;
|
||||||
|
import net.simon987.server.game.item.ItemVoid;
|
||||||
|
import net.simon987.server.game.objects.*;
|
||||||
import net.simon987.server.user.User;
|
import net.simon987.server.user.User;
|
||||||
|
import org.bson.Document;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.awt.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
public class Cubot extends GameObject implements Updatable, ControllableUnit, Programmable {
|
public class Cubot extends GameObject implements Updatable, ControllableUnit, MessageReceiver {
|
||||||
|
|
||||||
private static final char MAP_INFO = 0x0080;
|
private static final char MAP_INFO = 0x0200;
|
||||||
public static final int ID = 1;
|
|
||||||
|
|
||||||
public static int TYPE_ID = 2;
|
|
||||||
|
|
||||||
private int hologram = 0;
|
|
||||||
private String hologramString = "";
|
|
||||||
private HologramMode hologramMode = HologramMode.CLEARED;
|
|
||||||
private HologramMode lastHologramMode = HologramMode.CLEARED;
|
|
||||||
private int hologramColor = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hit points
|
* Hit points
|
||||||
*/
|
*/
|
||||||
private int hp;
|
private int hp;
|
||||||
private int heldItem;
|
/**
|
||||||
|
* Maximum hit points
|
||||||
|
*/
|
||||||
|
private int maxHp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shield points
|
||||||
|
*/
|
||||||
|
private int shield;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum shield points
|
||||||
|
*/
|
||||||
|
private int maxShield;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action that was set during the current tick. It is set to IDLE by default
|
||||||
|
*/
|
||||||
private Action currentAction = Action.IDLE;
|
private Action currentAction = Action.IDLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action at the end of the last tick
|
||||||
|
*/
|
||||||
private Action lastAction = Action.IDLE;
|
private Action lastAction = Action.IDLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status bit field that was set during the current tick. It is set to 0 by default
|
||||||
|
* <br>See CubotStatus and addStatus() method
|
||||||
|
*/
|
||||||
|
private char currentStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status bit field at the end of the last tick
|
||||||
|
*/
|
||||||
|
private char lastStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer of keypress codes. It is not changed between ticks and it is reset when
|
||||||
|
* the player uploads their code
|
||||||
|
*/
|
||||||
private ArrayList<Integer> keyboardBuffer = new ArrayList<>();
|
private ArrayList<Integer> keyboardBuffer = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer of console messages (also called 'internal buffer') that was set during the current tick
|
||||||
|
*/
|
||||||
private ArrayList<char[]> consoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE);
|
private ArrayList<char[]> consoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE);
|
||||||
|
/**
|
||||||
|
* Buffer of console messages (also called 'internal buffer') at the end of the last tick
|
||||||
|
*/
|
||||||
private ArrayList<char[]> lastConsoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE);
|
private ArrayList<char[]> lastConsoleMessagesBuffer = new ArrayList<>(CONSOLE_BUFFER_MAX_SIZE);
|
||||||
|
/**
|
||||||
|
* Console mode that was set during the current tick. It is set to NORMAL by default
|
||||||
|
*/
|
||||||
private ConsoleMode consoleMode = ConsoleMode.NORMAL;
|
private ConsoleMode consoleMode = ConsoleMode.NORMAL;
|
||||||
|
/**
|
||||||
|
* Console mode at the end of the last tick
|
||||||
|
*/
|
||||||
private ConsoleMode lastConsoleMode = ConsoleMode.NORMAL;
|
private ConsoleMode lastConsoleMode = ConsoleMode.NORMAL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User that controls this Cubot
|
||||||
|
*/
|
||||||
private User parent;
|
private User parent;
|
||||||
|
|
||||||
private int energy;
|
/**
|
||||||
private int maxEnergy;
|
* Maximum size of the console buffer (also called 'internal buffer')
|
||||||
|
*/
|
||||||
|
public static final int CONSOLE_BUFFER_MAX_SIZE = 40;
|
||||||
|
|
||||||
private static final float SOLAR_PANEL_MULTIPLIER = 1;
|
/**
|
||||||
private static final int CONSOLE_BUFFER_MAX_SIZE = 40;
|
* List of attached hardware, 'modules'
|
||||||
|
*/
|
||||||
|
private Map<Integer, HardwareModule> hardwareAddresses = new HashMap<>();
|
||||||
|
private Map<Class<? extends HardwareModule>, Integer> hardwareModules = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cubot's brain box
|
||||||
|
*/
|
||||||
|
private CPU cpu;
|
||||||
|
|
||||||
|
public enum ConsoleMode {
|
||||||
|
/**
|
||||||
|
* Used by the ComPort hardware - clears the console screen (client-side)
|
||||||
|
*/
|
||||||
|
CLEAR,
|
||||||
|
/**
|
||||||
|
* No specific client-side action
|
||||||
|
*/
|
||||||
|
NORMAL
|
||||||
|
}
|
||||||
|
|
||||||
public Cubot() {
|
public Cubot() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Cubot(Document document) {
|
||||||
|
super(document);
|
||||||
|
|
||||||
|
hp = document.getInteger("hp");
|
||||||
|
shield = document.getInteger("shield");
|
||||||
|
setDirection(Direction.getDirection(document.getInteger("direction")));
|
||||||
|
|
||||||
|
IServerConfiguration config = GameServer.INSTANCE.getConfig();
|
||||||
|
maxHp = config.getInt("cubot_max_hp");
|
||||||
|
maxShield = config.getInt("cubot_max_shield");
|
||||||
|
|
||||||
|
try {
|
||||||
|
cpu = CPU.deserialize((Document) document.get("cpu"), this);
|
||||||
|
|
||||||
|
ArrayList hardwareList = (ArrayList) document.get("hardware");
|
||||||
|
|
||||||
|
for (Object serialisedHw : hardwareList) {
|
||||||
|
HardwareModule hardware = GameServer.INSTANCE.getRegistry().deserializeHardware((Document) serialisedHw, this);
|
||||||
|
hardware.setCpu(cpu);
|
||||||
|
attachHardware(hardware, ((Document) serialisedHw).getInteger("address"));
|
||||||
|
}
|
||||||
|
} catch (CancelledException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char getMapInfo() {
|
public char getMapInfo() {
|
||||||
return MAP_INFO;
|
return MAP_INFO;
|
||||||
@ -58,14 +157,13 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
|
|
||||||
storeEnergy((int) (SOLAR_PANEL_MULTIPLIER * GameServer.INSTANCE.getDayNightCycle().getSunIntensity()));
|
|
||||||
|
|
||||||
if (currentAction == Action.WALKING) {
|
if (currentAction == Action.WALKING) {
|
||||||
if (spendEnergy(100)) {
|
if (spendEnergy(100)) {
|
||||||
if (!incrementLocation()) {
|
if (!incrementLocation()) {
|
||||||
//Couldn't walk
|
//Couldn't walk
|
||||||
currentAction = Action.IDLE;
|
currentAction = Action.IDLE;
|
||||||
|
}else{
|
||||||
|
GameServer.INSTANCE.getEventDispatcher().dispatch(new CubotWalkEvent(this));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentAction = Action.IDLE;
|
currentAction = Action.IDLE;
|
||||||
@ -81,8 +179,6 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
|
|||||||
currentAction = Action.IDLE;
|
currentAction = Action.IDLE;
|
||||||
|
|
||||||
//Same principle for hologram
|
//Same principle for hologram
|
||||||
lastHologramMode = hologramMode;
|
|
||||||
hologramMode = HologramMode.CLEARED;
|
|
||||||
|
|
||||||
//And the console
|
//And the console
|
||||||
lastConsoleMode = consoleMode;
|
lastConsoleMode = consoleMode;
|
||||||
@ -90,79 +186,118 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
|
|||||||
|
|
||||||
lastConsoleMessagesBuffer = new ArrayList<>(consoleMessagesBuffer);
|
lastConsoleMessagesBuffer = new ArrayList<>(consoleMessagesBuffer);
|
||||||
consoleMessagesBuffer.clear();
|
consoleMessagesBuffer.clear();
|
||||||
|
|
||||||
|
//And the status..
|
||||||
|
lastStatus = currentStatus;
|
||||||
|
currentStatus = 0;
|
||||||
|
|
||||||
|
for (HardwareModule module : hardwareAddresses.values()) {
|
||||||
|
module.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject serialise() {
|
public JSONObject jsonSerialise() {
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = super.jsonSerialise();
|
||||||
json.put("i", getObjectId());
|
|
||||||
json.put("t", ID);
|
|
||||||
json.put("x", getX());
|
|
||||||
json.put("y", getY());
|
|
||||||
json.put("direction", getDirection().ordinal());
|
json.put("direction", getDirection().ordinal());
|
||||||
|
CubotInventory inv = (CubotInventory) getHardware(CubotInventory.class);
|
||||||
|
int heldItem = inv.getInventory().getOrDefault(inv.getPosition(), new ItemVoid()).getId();
|
||||||
json.put("heldItem", heldItem);
|
json.put("heldItem", heldItem);
|
||||||
json.put("hp", hp);
|
json.put("hp", hp);
|
||||||
|
json.put("shield", shield);
|
||||||
json.put("action", lastAction.ordinal());
|
json.put("action", lastAction.ordinal());
|
||||||
json.put("holo", hologram);
|
|
||||||
json.put("holoStr", hologramString);
|
|
||||||
json.put("holoMode", lastHologramMode.ordinal());
|
|
||||||
json.put("holoC", hologramColor);
|
|
||||||
json.put("energy", energy);
|
|
||||||
|
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
json.put("parent", parent.getUsername()); //Only used client-side for now
|
json.put("parent", parent.getUsername()); //Only used client-side for now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (HardwareModule module : hardwareAddresses.values()) {
|
||||||
|
JSONObject hwJson = module.jsonSerialise();
|
||||||
|
if (hwJson != null) {
|
||||||
|
json.put(module.getClass().getName(), hwJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public Document mongoSerialise() {
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
Document dbObject = super.mongoSerialise();
|
||||||
|
|
||||||
dbObject.put("i", getObjectId());
|
|
||||||
dbObject.put("t", ID);
|
|
||||||
dbObject.put("x", getX());
|
|
||||||
dbObject.put("y", getY());
|
|
||||||
dbObject.put("direction", getDirection().ordinal());
|
dbObject.put("direction", getDirection().ordinal());
|
||||||
dbObject.put("heldItem", heldItem);
|
|
||||||
dbObject.put("hp", hp);
|
dbObject.put("hp", hp);
|
||||||
|
dbObject.put("shield", shield);
|
||||||
dbObject.put("action", lastAction.ordinal());
|
dbObject.put("action", lastAction.ordinal());
|
||||||
dbObject.put("holo", hologram);
|
|
||||||
dbObject.put("holoStr", hologramString);
|
|
||||||
dbObject.put("holoMode", lastHologramMode.ordinal());
|
|
||||||
dbObject.put("holoC", hologramColor);
|
|
||||||
dbObject.put("energy", energy);
|
|
||||||
|
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
dbObject.put("parent", parent.getUsername()); //Only used client-side for now
|
dbObject.put("parent", parent.getUsername()); //Only used client-side for now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Document> hardwareList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Integer address : hardwareAddresses.keySet()) {
|
||||||
|
|
||||||
|
HardwareModule hardware = hardwareAddresses.get(address);
|
||||||
|
|
||||||
|
Document serialisedHw = hardware.mongoSerialise();
|
||||||
|
serialisedHw.put("address", address);
|
||||||
|
hardwareList.add(serialisedHw);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbObject.put("hardware", hardwareList);
|
||||||
|
|
||||||
|
dbObject.put("cpu", cpu.mongoSerialise());
|
||||||
return dbObject;
|
return dbObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Cubot deserialize(DBObject obj) {
|
/**
|
||||||
|
* Reset to 'factory settings', as it were when it was first created
|
||||||
Cubot cubot = new Cubot();
|
*/
|
||||||
cubot.setObjectId((long) obj.get("i"));
|
private void reset() {
|
||||||
cubot.setX((int) obj.get("x"));
|
setDead(false);
|
||||||
cubot.setY((int) obj.get("y"));
|
setHp(maxHp);
|
||||||
cubot.hp = (int) obj.get("hp");
|
setShield(0);
|
||||||
cubot.setDirection(Direction.getDirection((int) obj.get("direction")));
|
setEnergy(((CubotBattery) getHardware(CubotBattery.class)).getMaxEnergy());
|
||||||
cubot.heldItem = (int) obj.get("heldItem");
|
clearKeyboardBuffer();
|
||||||
cubot.energy = (int) obj.get("energy");
|
consoleMessagesBuffer.clear();
|
||||||
cubot.maxEnergy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy");
|
lastConsoleMessagesBuffer.clear();
|
||||||
|
currentStatus = 0;
|
||||||
return cubot;
|
lastStatus = 0;
|
||||||
|
addStatus(CubotStatus.FACTORY_NEW);
|
||||||
|
|
||||||
|
for (HardwareModule module : hardwareAddresses.values()) {
|
||||||
|
module.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeldItem(int heldItem) {
|
@Override
|
||||||
this.heldItem = heldItem;
|
public boolean onDeadCallback() {
|
||||||
}
|
GameEvent event = new DeathEvent(this);
|
||||||
|
GameServer.INSTANCE.getEventDispatcher().dispatch(event);
|
||||||
|
|
||||||
public int getHeldItem() {
|
reset();
|
||||||
return heldItem;
|
|
||||||
|
//Teleport to spawn point
|
||||||
|
this.getWorld().removeObject(this);
|
||||||
|
this.getWorld().decUpdatable();
|
||||||
|
|
||||||
|
IServerConfiguration config = GameServer.INSTANCE.getConfig();
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
int spawnX = config.getInt("new_user_worldX") + random.nextInt(5);
|
||||||
|
int spawnY = config.getInt("new_user_worldY") + random.nextInt(5);
|
||||||
|
String dimension = config.getString("new_user_dimension");
|
||||||
|
this.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(spawnX, spawnY, true, dimension));
|
||||||
|
|
||||||
|
Point point = this.getWorld().getRandomPassableTile();
|
||||||
|
this.setX(point.x);
|
||||||
|
this.setY(point.y);
|
||||||
|
|
||||||
|
this.getWorld().addObject(this);
|
||||||
|
this.getWorld().incUpdatable();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -183,14 +318,15 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
|
|||||||
this.currentAction = currentAction;
|
this.currentAction = currentAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getParent() {
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setParent(User parent) {
|
public void setParent(User parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
public Action getAction() {
|
public Action getAction() {
|
||||||
return lastAction;
|
return lastAction;
|
||||||
}
|
}
|
||||||
@ -199,51 +335,83 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
|
|||||||
return currentAction;
|
return currentAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHologram(int hologram) {
|
|
||||||
this.hologram = hologram;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setHologramString(String hologramString) {
|
|
||||||
this.hologramString = hologramString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getEnergy() {
|
public int getEnergy() {
|
||||||
return energy;
|
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||||
|
return battery.getEnergy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnergy(int energy) {
|
public void setEnergy(int energy) {
|
||||||
this.energy = energy;
|
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||||
|
battery.setEnergy(energy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean spendEnergy(int spent) {
|
public boolean spendEnergy(int amount) {
|
||||||
|
|
||||||
if (energy - spent < 0) {
|
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||||
|
|
||||||
|
if (battery.getEnergy() - amount < 0) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
energy -= spent;
|
battery.setEnergy(battery.getEnergy() - amount);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeEnergy(int qty) {
|
public void storeEnergy(int amount) {
|
||||||
|
|
||||||
energy = Math.min(energy + qty, maxEnergy);
|
|
||||||
|
|
||||||
|
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||||
|
battery.setEnergy(Math.min(battery.getEnergy() + amount, battery.getMaxEnergy()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMaxEnergy(int maxEnergy) {
|
public void setMaxEnergy(int maxEnergy) {
|
||||||
this.maxEnergy = maxEnergy;
|
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||||
|
battery.setMaxEnergy(maxEnergy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxEnergy() {
|
public int getMaxEnergy() {
|
||||||
return maxEnergy;
|
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||||
|
return battery.getMaxEnergy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getShield() {
|
||||||
|
return shield;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShield(int shield) {
|
||||||
|
this.shield = shield;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean chargeShield(int amount) {
|
||||||
|
amount = Math.min(amount, maxShield - shield);
|
||||||
|
|
||||||
|
int energySpent = amount * CubotShield.COST;
|
||||||
|
if(spendEnergy(energySpent)) {
|
||||||
|
shield += amount;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Damages shield by amount.
|
||||||
|
*
|
||||||
|
* Return damage that broke through the shield.
|
||||||
|
*/
|
||||||
|
public int damageShield(int amount) {
|
||||||
|
int after = shield - amount;
|
||||||
|
if(after < 0) {
|
||||||
|
shield = 0;
|
||||||
|
return -after;
|
||||||
|
}
|
||||||
|
shield = after;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Memory getFloppyData() {
|
public Memory getFloppyData() {
|
||||||
|
|
||||||
CubotFloppyDrive drive = ((CubotFloppyDrive) getParent().getCpu().getHardware(CubotFloppyDrive.DEFAULT_ADDRESS));
|
CubotFloppyDrive drive = (CubotFloppyDrive) getHardware(CubotFloppyDrive.class);
|
||||||
|
|
||||||
if (drive.getFloppy() != null) {
|
if (drive.getFloppy() != null) {
|
||||||
return drive.getFloppy().getMemory();
|
return drive.getFloppy().getMemory();
|
||||||
@ -257,22 +425,6 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHologramMode(HologramMode hologramMode) {
|
|
||||||
this.hologramMode = hologramMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum HologramMode {
|
|
||||||
CLEARED,
|
|
||||||
HEX,
|
|
||||||
STRING,
|
|
||||||
DEC
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ConsoleMode {
|
|
||||||
CLEAR,
|
|
||||||
NORMAL
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAction(Action action) {
|
public void setAction(Action action) {
|
||||||
currentAction = action;
|
currentAction = action;
|
||||||
@ -302,7 +454,152 @@ public class Cubot extends GameObject implements Updatable, ControllableUnit, Pr
|
|||||||
this.consoleMode = consoleMode;
|
this.consoleMode = consoleMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHologramColor(int hologramColor) {
|
public void addStatus(CubotStatus status) {
|
||||||
this.hologramColor = hologramColor;
|
|
||||||
|
currentStatus |= status.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeStatus(CubotStatus status) {
|
||||||
|
|
||||||
|
currentStatus &= (~status.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
public char getStatus() {
|
||||||
|
return lastStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently has no effect
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setHealRate(int hp) {
|
||||||
|
//no op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHp() {
|
||||||
|
return hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHp(int hp) {
|
||||||
|
this.hp = hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxHp() {
|
||||||
|
return maxHp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxHp(int hp) {
|
||||||
|
this.maxHp = hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxShield() {
|
||||||
|
return maxShield;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxShield(int maxShield) {
|
||||||
|
this.maxShield = maxShield;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void heal(int amount) {
|
||||||
|
hp += amount;
|
||||||
|
|
||||||
|
//Can't heal above max
|
||||||
|
if (hp > maxHp) {
|
||||||
|
hp = maxHp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void damage(int amount) {
|
||||||
|
|
||||||
|
//Damage shield first
|
||||||
|
int hullDamage = damageShield(amount);
|
||||||
|
|
||||||
|
hp -= hullDamage;
|
||||||
|
|
||||||
|
if (hp <= 0) {
|
||||||
|
setDead(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attachHardware(HardwareModule hardware, int address) {
|
||||||
|
hardwareAddresses.put(address, hardware);
|
||||||
|
hardwareModules.put(hardware.getClass(), address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detachHardware(int address) {
|
||||||
|
hardwareAddresses.remove(address);
|
||||||
|
|
||||||
|
Class<? extends HardwareModule> toRemove = null;
|
||||||
|
for (Class<? extends HardwareModule> clazz : hardwareModules.keySet()) {
|
||||||
|
if (hardwareModules.get(clazz) == address) {
|
||||||
|
toRemove = clazz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hardwareModules.remove(toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hardwareInterrupt(int address, Status status) {
|
||||||
|
HardwareModule hardware = hardwareAddresses.get(address);
|
||||||
|
|
||||||
|
if (hardware != null) {
|
||||||
|
hardware.handleInterrupt(status);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hardwareQuery(int address) {
|
||||||
|
HardwareModule hardware = hardwareAddresses.get(address);
|
||||||
|
|
||||||
|
if (hardware != null) {
|
||||||
|
return hardware.getId();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HardwareModule getHardware(Class<? extends HardwareModule> clazz) {
|
||||||
|
return hardwareAddresses.get(hardwareModules.get(clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
public HardwareModule getHardware(int address) {
|
||||||
|
return hardwareAddresses.get(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CPU getCpu() {
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCpu(CPU cpu) {
|
||||||
|
this.cpu = cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void giveItem(Item item) {
|
||||||
|
//Overwrite item at current position
|
||||||
|
((CubotInventory) getHardware(CubotInventory.class)).putItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder str = new StringBuilder(super.toString());
|
||||||
|
|
||||||
|
str.append("\nHardware: \n");
|
||||||
|
for (Integer i : hardwareAddresses.keySet()) {
|
||||||
|
str.append(String.format("%04X", i)).append(":").append(hardwareAddresses.get(i)).append("\n");
|
||||||
|
}
|
||||||
|
return str.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
public class CubotBattery extends CpuHardware {
|
public class CubotBattery extends HardwareModule {
|
||||||
|
|
||||||
public static final int DEFAULT_ADDRESS = 0x000A;
|
public static final int DEFAULT_ADDRESS = 0x000A;
|
||||||
|
|
||||||
@ -14,13 +15,38 @@ public class CubotBattery extends CpuHardware {
|
|||||||
* Hardware ID (Should be unique)
|
* Hardware ID (Should be unique)
|
||||||
*/
|
*/
|
||||||
public static final char HWID = 0x000A;
|
public static final char HWID = 0x000A;
|
||||||
|
/**
|
||||||
|
* Solar panel multiplier
|
||||||
|
* <br>TODO: Set this constant in dimension
|
||||||
|
*/
|
||||||
|
private static final float SOLAR_PANEL_MULTIPLIER = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Energy units in kJ
|
||||||
|
*/
|
||||||
|
private int energy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum energy units in kJ
|
||||||
|
*/
|
||||||
|
private int maxEnergy;
|
||||||
|
|
||||||
|
|
||||||
private Cubot cubot;
|
|
||||||
private static final int BATTERY_POLL = 1;
|
private static final int BATTERY_POLL = 1;
|
||||||
private static final int BATTERY_GET_MAX_CAPACITY = 2;
|
private static final int BATTERY_GET_MAX_CAPACITY = 2;
|
||||||
|
|
||||||
public CubotBattery(Cubot cubot) {
|
public CubotBattery(ControllableUnit unit) {
|
||||||
this.cubot = cubot;
|
super(null, unit);
|
||||||
|
|
||||||
|
energy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy");
|
||||||
|
maxEnergy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy");
|
||||||
|
}
|
||||||
|
|
||||||
|
public CubotBattery(Document document, ControllableUnit cubot) {
|
||||||
|
super(document, cubot);
|
||||||
|
|
||||||
|
energy = document.getInteger("energy");
|
||||||
|
maxEnergy = document.getInteger("max_energy");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -29,14 +55,12 @@ public class CubotBattery extends CpuHardware {
|
|||||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||||
|
|
||||||
if (a == BATTERY_POLL) {
|
if (a == BATTERY_POLL) {
|
||||||
getCpu().getRegisterSet().getRegister("B").setValue(cubot.getEnergy());
|
getCpu().getRegisterSet().getRegister("B").setValue(energy);
|
||||||
|
|
||||||
} else if (a == BATTERY_GET_MAX_CAPACITY) {
|
} else if (a == BATTERY_GET_MAX_CAPACITY) {
|
||||||
getCpu().getRegisterSet().getRegister("B").setValue(cubot.getMaxEnergy());
|
getCpu().getRegisterSet().getRegister("B").setValue(maxEnergy);
|
||||||
} else if (a == 0xFFFF) {
|
|
||||||
cubot.setEnergy(cubot.getMaxEnergy());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -45,19 +69,52 @@ public class CubotBattery extends CpuHardware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public JSONObject jsonSerialise() {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
json.put("energy", energy);
|
||||||
|
|
||||||
dbObject.put("hwid", (int) HWID);
|
return json;
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject debugJsonSerialise() {
|
||||||
|
JSONObject json = jsonSerialise();
|
||||||
|
|
||||||
public static CubotBattery deserialize(DBObject obj) {
|
json.put("max_energy", maxEnergy);
|
||||||
return new CubotBattery((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document document = super.mongoSerialise();
|
||||||
|
|
||||||
|
document.put("energy", energy);
|
||||||
|
document.put("max_energy", maxEnergy);
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEnergy() {
|
||||||
|
return energy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnergy(int energy) {
|
||||||
|
this.energy = energy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxEnergy() {
|
||||||
|
return maxEnergy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxEnergy(int maxEnergy) {
|
||||||
|
this.maxEnergy = maxEnergy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
energy = Math.min(maxEnergy,
|
||||||
|
energy + (int) (SOLAR_PANEL_MULTIPLIER * GameServer.INSTANCE.getDayNightCycle().getSunIntensity()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,32 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
import net.simon987.server.game.GameObject;
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
import net.simon987.server.game.Programmable;
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
import net.simon987.server.game.objects.MessageReceiver;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class CubotComPort extends CpuHardware {
|
public class CubotComPort extends HardwareModule {
|
||||||
|
|
||||||
public static final char HWID = 0xD;
|
public static final char HWID = 0xD;
|
||||||
public static final int DEFAULT_ADDRESS = 0xD;
|
public static final int DEFAULT_ADDRESS = 0xD;
|
||||||
|
|
||||||
private Cubot cubot;
|
|
||||||
|
|
||||||
private static final int COMPORT_BUFFER_CLEAR = 0;
|
private static final int COMPORT_BUFFER_CLEAR = 0;
|
||||||
private static final int COMPORT_POLL = 1;
|
private static final int COMPORT_POLL = 1;
|
||||||
private static final int COMPORT_FRONT_PORT_OUT = 2;
|
private static final int COMPORT_FRONT_PORT_OUT = 2;
|
||||||
private static final int COMPORT_SELF_OUT = 3;
|
private static final int COMPORT_SELF_OUT = 3;
|
||||||
private static final int COMPORT_CONSOLE_CLEAR = 4;
|
private static final int COMPORT_CONSOLE_CLEAR = 4;
|
||||||
|
|
||||||
public CubotComPort(Cubot cubot) {
|
public CubotComPort(ControllableUnit unit) {
|
||||||
this.cubot = cubot;
|
super(null, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CubotComPort(Document document, ControllableUnit cubot) {
|
||||||
|
super(document, cubot);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int MESSAGE_LENGTH = 8;
|
private static final int MESSAGE_LENGTH = 8;
|
||||||
@ -37,21 +38,23 @@ public class CubotComPort extends CpuHardware {
|
|||||||
|
|
||||||
if (a == COMPORT_BUFFER_CLEAR) {
|
if (a == COMPORT_BUFFER_CLEAR) {
|
||||||
|
|
||||||
cubot.getConsoleMessagesBuffer().clear();
|
unit.getConsoleMessagesBuffer().clear();
|
||||||
|
|
||||||
} else if (a == COMPORT_CONSOLE_CLEAR) {
|
} else if (a == COMPORT_CONSOLE_CLEAR) {
|
||||||
|
|
||||||
cubot.setConsoleMode(Cubot.ConsoleMode.CLEAR);
|
if (unit instanceof Cubot) {
|
||||||
|
((Cubot) unit).setConsoleMode(Cubot.ConsoleMode.CLEAR);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (a == COMPORT_POLL) {
|
} else if (a == COMPORT_POLL) {
|
||||||
|
|
||||||
if (cubot.spendEnergy(4)) {
|
if (unit.spendEnergy(4)) {
|
||||||
|
|
||||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
|
|
||||||
//Read all messages in the console buffer to memory at X
|
//Read all messages in the console buffer to memory at X
|
||||||
|
|
||||||
for (char[] message : cubot.getConsoleMessagesBuffer()) {
|
for (char[] message : unit.getConsoleMessagesBuffer()) {
|
||||||
if (x + MESSAGE_LENGTH >= getCpu().getMemory().getWords().length) {
|
if (x + MESSAGE_LENGTH >= getCpu().getMemory().getWords().length) {
|
||||||
//todo set interrupt ?
|
//todo set interrupt ?
|
||||||
getCpu().getStatus().setErrorFlag(true);
|
getCpu().getStatus().setErrorFlag(true);
|
||||||
@ -61,19 +64,19 @@ public class CubotComPort extends CpuHardware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Set B = number of messages
|
//Set B = number of messages
|
||||||
getCpu().getRegisterSet().getRegister("B").setValue(cubot.getConsoleMessagesBuffer().size());
|
getCpu().getRegisterSet().getRegister("B").setValue(unit.getConsoleMessagesBuffer().size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (a == COMPORT_FRONT_PORT_OUT) {
|
} else if (a == COMPORT_FRONT_PORT_OUT) {
|
||||||
|
|
||||||
if (cubot.spendEnergy(20)) {
|
if (unit.spendEnergy(5)) {
|
||||||
//Get object directly in front of the Cubot
|
//Get object directly in front of the Cubot
|
||||||
Point frontTile = cubot.getFrontTile();
|
Point frontTile = unit.getFrontTile();
|
||||||
//Todo will have to add getGameObjectsBlockingAt to enable Factory
|
//Todo will have to add getGameObjectsBlockingAt to enable Factory
|
||||||
ArrayList<GameObject> objects = cubot.getWorld().getGameObjectsAt(frontTile.x, frontTile.y);
|
ArrayList<GameObject> objects = unit.getWorld().getGameObjectsAt(frontTile.x, frontTile.y);
|
||||||
|
|
||||||
if (objects.size() > 0 && objects.get(0) instanceof Programmable) {
|
if (objects.size() > 0 && objects.get(0) instanceof MessageReceiver) {
|
||||||
|
|
||||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
|
|
||||||
@ -86,9 +89,9 @@ public class CubotComPort extends CpuHardware {
|
|||||||
char[] message = new char[MESSAGE_LENGTH];
|
char[] message = new char[MESSAGE_LENGTH];
|
||||||
System.arraycopy(getCpu().getMemory().getWords(), x, message, 0, MESSAGE_LENGTH);
|
System.arraycopy(getCpu().getMemory().getWords(), x, message, 0, MESSAGE_LENGTH);
|
||||||
|
|
||||||
//Send it to the Programmable object
|
//Send it to the MessageReceiver object
|
||||||
getCpu().getRegisterSet().getRegister("B").setValue(
|
getCpu().getRegisterSet().getRegister("B").setValue(
|
||||||
((Programmable) objects.get(0)).sendMessage(message) ? 1 : 0);
|
((MessageReceiver) objects.get(0)).sendMessage(message) ? 1 : 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,7 +101,7 @@ public class CubotComPort extends CpuHardware {
|
|||||||
|
|
||||||
} else if (a == COMPORT_SELF_OUT) {
|
} else if (a == COMPORT_SELF_OUT) {
|
||||||
|
|
||||||
if (cubot.spendEnergy(1)) {
|
if (unit.spendEnergy(1)) {
|
||||||
|
|
||||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
|
|
||||||
@ -111,34 +114,17 @@ public class CubotComPort extends CpuHardware {
|
|||||||
//Get MESSAGE_LENGTH-word message pointed by X
|
//Get MESSAGE_LENGTH-word message pointed by X
|
||||||
char[] message = new char[MESSAGE_LENGTH];
|
char[] message = new char[MESSAGE_LENGTH];
|
||||||
System.arraycopy(getCpu().getMemory().getWords(), x, message, 0, MESSAGE_LENGTH);
|
System.arraycopy(getCpu().getMemory().getWords(), x, message, 0, MESSAGE_LENGTH);
|
||||||
getCpu().getRegisterSet().getRegister("B").setValue(cubot.sendMessage(message) ? 1 : 0);
|
getCpu().getRegisterSet().getRegister("B").setValue(unit.sendMessage(message) ? 1 : 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getCpu().getRegisterSet().getRegister("B").setValue(0); //Failed
|
getCpu().getRegisterSet().getRegister("B").setValue(0); //Failed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char getId() {
|
public char getId() {
|
||||||
return HWID;
|
return HWID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BasicDBObject mongoSerialise() {
|
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
|
||||||
|
|
||||||
dbObject.put("hwid", (int) HWID);
|
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CubotComPort deserialize(DBObject obj) {
|
|
||||||
return new CubotComPort((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
public class CubotCore extends HardwareModule {
|
||||||
|
|
||||||
|
public static final int DEFAULT_ADDRESS = 0x000E;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hardware ID (Should be unique)
|
||||||
|
*/
|
||||||
|
public static final char HWID = 0x000E;
|
||||||
|
|
||||||
|
private static final int CORE_STATUS_POLL = 1;
|
||||||
|
private static final int CORE_HULL_POLL = 2;
|
||||||
|
|
||||||
|
public CubotCore(ControllableUnit unit) {
|
||||||
|
super(null, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CubotCore(Document document, ControllableUnit unit) {
|
||||||
|
super(document, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleInterrupt(Status status) {
|
||||||
|
|
||||||
|
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||||
|
|
||||||
|
if (a == CORE_STATUS_POLL) {
|
||||||
|
if (unit instanceof Cubot) {
|
||||||
|
getCpu().getRegisterSet().getRegister("B").setValue(((Cubot) unit).getStatus());
|
||||||
|
}
|
||||||
|
} else if (a == CORE_HULL_POLL) {
|
||||||
|
getCpu().getRegisterSet().getRegister("B").setValue(unit.getHp());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getId() {
|
||||||
|
return HWID;
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,14 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
import net.simon987.server.game.Action;
|
import net.simon987.server.game.item.Item;
|
||||||
import net.simon987.server.game.TileMap;
|
import net.simon987.server.game.objects.Action;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import net.simon987.server.game.world.Tile;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
public class CubotDrill extends CpuHardware {
|
public class CubotDrill extends HardwareModule {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hardware ID (Should be unique)
|
* Hardware ID (Should be unique)
|
||||||
@ -20,10 +20,12 @@ public class CubotDrill extends CpuHardware {
|
|||||||
private static final int DRILL_POLL = 1;
|
private static final int DRILL_POLL = 1;
|
||||||
private static final int DRILL_GATHER = 2; // simplified gather
|
private static final int DRILL_GATHER = 2; // simplified gather
|
||||||
|
|
||||||
private Cubot cubot;
|
public CubotDrill(ControllableUnit unit) {
|
||||||
|
super(null, unit);
|
||||||
|
}
|
||||||
|
|
||||||
public CubotDrill(Cubot cubot) {
|
public CubotDrill(Document document, ControllableUnit cubot) {
|
||||||
this.cubot = cubot;
|
super(document, cubot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -41,38 +43,18 @@ public class CubotDrill extends CpuHardware {
|
|||||||
|
|
||||||
} else if (a == DRILL_GATHER) {
|
} else if (a == DRILL_GATHER) {
|
||||||
|
|
||||||
if (cubot.spendEnergy(1400)) {
|
if (unit.spendEnergy(1400)) {
|
||||||
if (cubot.getCurrentAction() == Action.IDLE) {
|
if (unit.getCurrentAction() == Action.IDLE) {
|
||||||
int tile = cubot.getWorld().getTileMap().getTileAt(cubot.getX(), cubot.getY());
|
|
||||||
|
|
||||||
if (tile == TileMap.IRON_TILE) {
|
Tile tile = unit.getWorld().getTileMap().getTileAt(unit.getX(), unit.getY());
|
||||||
cubot.setHeldItem(TileMap.ITEM_IRON);
|
|
||||||
cubot.setCurrentAction(Action.DIGGING);
|
|
||||||
|
|
||||||
} else if (tile == TileMap.COPPER_TILE) {
|
|
||||||
cubot.setHeldItem(TileMap.ITEM_COPPER);
|
|
||||||
cubot.setCurrentAction(Action.DIGGING);
|
|
||||||
|
|
||||||
|
Item newItem = tile.drill();
|
||||||
|
if (newItem != null) {
|
||||||
|
unit.setCurrentAction(Action.DIGGING);
|
||||||
|
unit.giveItem(newItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BasicDBObject mongoSerialise() {
|
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
|
||||||
|
|
||||||
dbObject.put("hwid", (int) HWID);
|
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CubotDrill deserialize(DBObject obj) {
|
|
||||||
return new CubotDrill((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
public class CubotFloppyDrive extends CpuHardware {
|
public class CubotFloppyDrive extends CubotHardwareModule {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hardware ID (Should be unique)
|
* Hardware ID (Should be unique)
|
||||||
@ -19,15 +17,24 @@ public class CubotFloppyDrive extends CpuHardware {
|
|||||||
private static final int FLOPPY_READ_SECTOR = 2;
|
private static final int FLOPPY_READ_SECTOR = 2;
|
||||||
private static final int FLOPPY_WRITE_SECTOR = 3;
|
private static final int FLOPPY_WRITE_SECTOR = 3;
|
||||||
|
|
||||||
private Cubot cubot;
|
|
||||||
private FloppyDisk floppyDisk;
|
private FloppyDisk floppyDisk;
|
||||||
|
|
||||||
public CubotFloppyDrive(Cubot cubot) {
|
public CubotFloppyDrive(Cubot cubot) {
|
||||||
this.cubot = cubot;
|
super(cubot);
|
||||||
|
|
||||||
floppyDisk = new FloppyDisk();
|
floppyDisk = new FloppyDisk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CubotFloppyDrive(Document document, ControllableUnit cubot) {
|
||||||
|
super(document, cubot);
|
||||||
|
|
||||||
|
if (document.containsKey("floppy")) {
|
||||||
|
floppyDisk = new FloppyDisk((Document) document.get("floppy"));
|
||||||
|
} else {
|
||||||
|
floppyDisk = new FloppyDisk();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInterrupt(Status status) {
|
public void handleInterrupt(Status status) {
|
||||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||||
@ -51,7 +58,7 @@ public class CubotFloppyDrive extends CpuHardware {
|
|||||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
int y = getCpu().getRegisterSet().getRegister("Y").getValue();
|
int y = getCpu().getRegisterSet().getRegister("Y").getValue();
|
||||||
|
|
||||||
floppyDisk.readSector(x, cubot.getParent().getCpu().getMemory(), y);
|
floppyDisk.readSector(x, cubot.getCpu().getMemory(), y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +73,7 @@ public class CubotFloppyDrive extends CpuHardware {
|
|||||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
int y = getCpu().getRegisterSet().getRegister("Y").getValue();
|
int y = getCpu().getRegisterSet().getRegister("Y").getValue();
|
||||||
|
|
||||||
floppyDisk.writeSector(x, cubot.getParent().getCpu().getMemory(), y);
|
floppyDisk.writeSector(x, cubot.getCpu().getMemory(), y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,31 +85,6 @@ public class CubotFloppyDrive extends CpuHardware {
|
|||||||
return HWID;
|
return HWID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BasicDBObject mongoSerialise() {
|
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
|
||||||
|
|
||||||
dbObject.put("hwid", (int) HWID);
|
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
if (floppyDisk != null) {
|
|
||||||
dbObject.put("floppy", floppyDisk.mongoSerialise());
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CubotFloppyDrive deserialize(DBObject obj) {
|
|
||||||
|
|
||||||
CubotFloppyDrive drive = new CubotFloppyDrive((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
|
||||||
|
|
||||||
if (obj.containsField("floppy")) {
|
|
||||||
drive.floppyDisk = FloppyDisk.deserialise((DBObject) obj.get("floppy"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return drive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FloppyDisk getFloppy() {
|
public FloppyDisk getFloppy() {
|
||||||
return floppyDisk;
|
return floppyDisk;
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
public abstract class CubotHardwareModule extends HardwareModule {
|
||||||
|
|
||||||
|
protected Cubot cubot;
|
||||||
|
|
||||||
|
public CubotHardwareModule(Document document, ControllableUnit cubot) {
|
||||||
|
this.cubot = (Cubot) cubot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CubotHardwareModule(Cubot cubot) {
|
||||||
|
this.cubot = cubot;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,23 +1,19 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
public class CubotHologram extends CpuHardware {
|
public class CubotHologram extends HardwareModule {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hardware ID (Should be unique)
|
* Hardware ID (Should be unique)
|
||||||
*/
|
*/
|
||||||
static final char HWID = 0x0009;
|
static final char HWID = 0x0009;
|
||||||
|
|
||||||
public static final int DEFAULT_ADDRESS = 9;
|
public static final int DEFAULT_ADDRESS = 9;
|
||||||
|
|
||||||
private Cubot cubot;
|
|
||||||
|
|
||||||
private static final int HOLO_CLEAR = 0;
|
private static final int HOLO_CLEAR = 0;
|
||||||
private static final int HOLO_DISPLAY_HEX = 1;
|
private static final int HOLO_DISPLAY_HEX = 1;
|
||||||
private static final int HOLO_DISPLAY_STRING = 2;
|
private static final int HOLO_DISPLAY_STRING = 2;
|
||||||
@ -26,8 +22,27 @@ public class CubotHologram extends CpuHardware {
|
|||||||
|
|
||||||
private static final int STR_MAX_LEN = 8;
|
private static final int STR_MAX_LEN = 8;
|
||||||
|
|
||||||
public CubotHologram(Cubot cubot) {
|
private int displayValue = 0;
|
||||||
this.cubot = cubot;
|
private String displayString = "";
|
||||||
|
private HologramMode mode = HologramMode.CLEARED;
|
||||||
|
private HologramMode lastMode = HologramMode.CLEARED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hologram color code. Format is handled by the client
|
||||||
|
*/
|
||||||
|
private int displayColor = 0;
|
||||||
|
|
||||||
|
public CubotHologram(ControllableUnit unit) {
|
||||||
|
super(null, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CubotHologram(Document document, ControllableUnit cubot) {
|
||||||
|
super(document, cubot);
|
||||||
|
|
||||||
|
displayValue = document.getInteger("value");
|
||||||
|
displayColor = document.getInteger("color");
|
||||||
|
displayString = document.getString("string");
|
||||||
|
mode = HologramMode.values()[document.getInteger("mode")];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -36,11 +51,10 @@ public class CubotHologram extends CpuHardware {
|
|||||||
char a = getCpu().getRegisterSet().getRegister("A").getValue();
|
char a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||||
|
|
||||||
if (a == HOLO_CLEAR) {
|
if (a == HOLO_CLEAR) {
|
||||||
cubot.setHologramMode(Cubot.HologramMode.CLEARED);
|
mode = HologramMode.CLEARED;
|
||||||
} else if (a == HOLO_DISPLAY_HEX) {
|
} else if (a == HOLO_DISPLAY_HEX) {
|
||||||
char b = getCpu().getRegisterSet().getRegister("B").getValue();
|
displayValue = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||||
cubot.setHologram(b);
|
mode = HologramMode.HEX;
|
||||||
cubot.setHologramMode(Cubot.HologramMode.HEX);
|
|
||||||
} else if (a == HOLO_DISPLAY_STRING) {
|
} else if (a == HOLO_DISPLAY_STRING) {
|
||||||
char x = getCpu().getRegisterSet().getRegister("X").getValue();
|
char x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
//Display zero-terminated string starting at X (max 8 chars)
|
//Display zero-terminated string starting at X (max 8 chars)
|
||||||
@ -58,21 +72,20 @@ public class CubotHologram extends CpuHardware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cubot.setHologramString(holoString.toString());
|
displayString = holoString.toString();
|
||||||
cubot.setHologramMode(Cubot.HologramMode.STRING);
|
mode = HologramMode.STRING;
|
||||||
} else if (a == HOLO_DISPLAY_DEC) {
|
} else if (a == HOLO_DISPLAY_DEC) {
|
||||||
//Display decimal number
|
//Display decimal number
|
||||||
char b = getCpu().getRegisterSet().getRegister("B").getValue();
|
displayValue = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||||
cubot.setHologram(b);
|
mode = HologramMode.DEC;
|
||||||
cubot.setHologramMode(Cubot.HologramMode.DEC);
|
|
||||||
|
|
||||||
} else if (a == HOLO_DISPLAY_COLOR) {
|
} else if (a == HOLO_DISPLAY_COLOR) {
|
||||||
|
|
||||||
if (cubot.spendEnergy(4)) {
|
if (unit.spendEnergy(4)) {
|
||||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||||
int c = getCpu().getRegisterSet().getRegister("C").getValue();
|
int c = getCpu().getRegisterSet().getRegister("C").getValue();
|
||||||
|
|
||||||
cubot.setHologramColor((c | (b << 16))); //B:C
|
displayColor = (c | (b << 16)); //B:C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,19 +96,69 @@ public class CubotHologram extends CpuHardware {
|
|||||||
return HWID;
|
return HWID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CubotHologram deserialize(DBObject obj) {
|
@Override
|
||||||
return new CubotHologram((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
public Document mongoSerialise() {
|
||||||
|
Document document = super.mongoSerialise();
|
||||||
|
|
||||||
|
document.put("color", displayColor);
|
||||||
|
document.put("value", displayValue);
|
||||||
|
document.put("string", displayString);
|
||||||
|
document.put("mode", lastMode.ordinal());
|
||||||
|
|
||||||
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public JSONObject debugJsonSerialise() {
|
||||||
|
JSONObject json = jsonSerialise();
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
json.put("lastmode", mode);
|
||||||
|
|
||||||
dbObject.put("hwid", (int) HWID);
|
return json;
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject jsonSerialise() {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
|
||||||
|
json.put("color", displayColor);
|
||||||
|
json.put("value", displayValue);
|
||||||
|
json.put("string", displayString);
|
||||||
|
json.put("mode", lastMode.ordinal());
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum HologramMode {
|
||||||
|
/**
|
||||||
|
* Display nothing
|
||||||
|
*/
|
||||||
|
CLEARED,
|
||||||
|
/**
|
||||||
|
* Display value as hexadecimal in format 0x0000
|
||||||
|
*/
|
||||||
|
HEX,
|
||||||
|
/**
|
||||||
|
* Display string
|
||||||
|
*/
|
||||||
|
STRING,
|
||||||
|
/**
|
||||||
|
* Display value as decimal
|
||||||
|
*/
|
||||||
|
DEC
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
displayValue = 0;
|
||||||
|
displayColor = 0;
|
||||||
|
displayString = "";
|
||||||
|
mode = HologramMode.CLEARED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
lastMode = mode;
|
||||||
|
mode = HologramMode.CLEARED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.game.item.Item;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
public class CubotInventory extends CpuHardware {
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class CubotInventory extends HardwareModule {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hardware ID (Should be unique)
|
* Hardware ID (Should be unique)
|
||||||
@ -15,13 +19,63 @@ public class CubotInventory extends CpuHardware {
|
|||||||
|
|
||||||
public static final int DEFAULT_ADDRESS = 6;
|
public static final int DEFAULT_ADDRESS = 6;
|
||||||
|
|
||||||
private Cubot cubot;
|
|
||||||
|
|
||||||
private static final int INV_CLEAR = 0;
|
private static final int INV_CLEAR = 0;
|
||||||
private static final int INV_POLL = 1;
|
private static final int INV_POLL = 1;
|
||||||
|
private static final int INV_SEEK = 2;
|
||||||
|
private static final int INV_SCAN = 3;
|
||||||
|
|
||||||
public CubotInventory(Cubot cubot) {
|
private int inventorySize = 4; //TODO: load from config
|
||||||
this.cubot = cubot;
|
private Map<Integer, Item> inventory;
|
||||||
|
private int position = 0;
|
||||||
|
|
||||||
|
|
||||||
|
public CubotInventory(ControllableUnit unit) {
|
||||||
|
super(null, unit);
|
||||||
|
|
||||||
|
inventory = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CubotInventory(Document document, ControllableUnit cubot) {
|
||||||
|
super(document, cubot);
|
||||||
|
|
||||||
|
position = document.getInteger("position");
|
||||||
|
inventorySize = document.getInteger("size");
|
||||||
|
|
||||||
|
inventory = new HashMap<>();
|
||||||
|
for (String i : ((Map<String, Document>) document.get("inventory")).keySet()) {
|
||||||
|
inventory.put(Integer.valueOf(i),
|
||||||
|
GameServer.INSTANCE.getRegistry().deserializeItem(((Map<String, Document>) document.get("inventory")).get(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putItem(Item item) {
|
||||||
|
inventory.put(position, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scanItem() {
|
||||||
|
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
|
Item item = inventory.get(position);
|
||||||
|
item.digitize(unit.getCpu().getMemory(), x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Item clearItem() {
|
||||||
|
Item item = inventory.get(position);
|
||||||
|
item.clear(unit);
|
||||||
|
inventory.remove(position);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosition(int inventoryPosition) {
|
||||||
|
this.position = inventoryPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Integer, Item> getInventory() {
|
||||||
|
return inventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -35,34 +89,54 @@ public class CubotInventory extends CpuHardware {
|
|||||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||||
|
|
||||||
if (a == INV_POLL) {
|
if (a == INV_POLL) {
|
||||||
getCpu().getRegisterSet().getRegister("B").setValue(cubot.getHeldItem());
|
Item item = inventory.get(position);
|
||||||
|
char result;
|
||||||
|
if (item == null) {
|
||||||
|
result = 0;
|
||||||
|
} else {
|
||||||
|
result = item.poll();
|
||||||
|
}
|
||||||
|
getCpu().getRegisterSet().getRegister("B").setValue(result);
|
||||||
|
|
||||||
} else if (a == INV_CLEAR) {
|
} else if (a == INV_CLEAR) {
|
||||||
if (cubot.getHeldItem() == 0x0001) {
|
if (unit.spendEnergy(100)) {
|
||||||
int energy = GameServer.INSTANCE.getConfig().getInt("biomassEnergyValue");
|
clearItem();
|
||||||
cubot.storeEnergy(energy);
|
}
|
||||||
cubot.setHeldItem(0);
|
} else if (a == INV_SEEK) {
|
||||||
|
setPosition(getCpu().getRegisterSet().getRegister("X").getValue());
|
||||||
} else if (cubot.spendEnergy(100)) {
|
} else if (a == INV_SCAN) {
|
||||||
cubot.setHeldItem(0);
|
if (unit.spendEnergy(200)) {
|
||||||
|
scanItem();
|
||||||
|
clearItem();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document document = super.mongoSerialise();
|
||||||
|
|
||||||
|
document.put("position", position);
|
||||||
|
document.put("size", inventorySize);
|
||||||
|
|
||||||
|
Document items = new Document();
|
||||||
|
|
||||||
|
for (Integer i : inventory.keySet()) {
|
||||||
|
items.put(i.toString(), inventory.get(i).mongoSerialise());
|
||||||
|
}
|
||||||
|
|
||||||
|
document.put("inventory", items);
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public String toString() {
|
||||||
|
String itemList = "";
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
for (Integer i : inventory.keySet()) {
|
||||||
|
itemList += i + ": " + inventory.get(i).getClass().getSimpleName() + ", ";
|
||||||
dbObject.put("hwid", (int) HWID);
|
}
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
return String.format("{CubotInventory[%d/%d] @ %d [%s]}", inventory.size(), inventorySize, position, itemList);
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CubotInventory deserialize(DBObject obj) {
|
|
||||||
return new CubotInventory((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
public class CubotKeyboard extends CpuHardware {
|
public class CubotKeyboard extends CubotHardwareModule {
|
||||||
|
|
||||||
public static final int DEFAULT_ADDRESS = 4;
|
public static final int DEFAULT_ADDRESS = 4;
|
||||||
|
|
||||||
@ -18,10 +16,12 @@ public class CubotKeyboard extends CpuHardware {
|
|||||||
*/
|
*/
|
||||||
public static final char HWID = 0x0004;
|
public static final char HWID = 0x0004;
|
||||||
|
|
||||||
private Cubot cubot;
|
|
||||||
|
|
||||||
public CubotKeyboard(Cubot cubot) {
|
public CubotKeyboard(Cubot cubot) {
|
||||||
this.cubot = cubot;
|
super(cubot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CubotKeyboard(Document document, ControllableUnit cubot) {
|
||||||
|
super(document, cubot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -51,19 +51,4 @@ public class CubotKeyboard extends CpuHardware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BasicDBObject mongoSerialise() {
|
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
|
||||||
|
|
||||||
dbObject.put("hwid", (int) HWID);
|
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CubotKeyboard deserialize(DBObject obj) {
|
|
||||||
return new CubotKeyboard((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
import net.simon987.server.game.Action;
|
import net.simon987.server.game.objects.*;
|
||||||
import net.simon987.server.game.Attackable;
|
import org.bson.Document;
|
||||||
import net.simon987.server.game.GameObject;
|
|
||||||
import net.simon987.server.game.InventoryHolder;
|
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class CubotLaser extends CpuHardware {
|
public class CubotLaser extends HardwareModule {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hardware ID (Should be unique)
|
* Hardware ID (Should be unique)
|
||||||
@ -22,16 +18,18 @@ public class CubotLaser extends CpuHardware {
|
|||||||
|
|
||||||
public static final int DEFAULT_ADDRESS = 2;
|
public static final int DEFAULT_ADDRESS = 2;
|
||||||
|
|
||||||
private Cubot cubot;
|
|
||||||
|
|
||||||
private static final int LASER_WITHDRAW = 1;
|
private static final int LASER_WITHDRAW = 1;
|
||||||
private static final int LASER_DEPOSIT = 2;
|
private static final int LASER_DEPOSIT = 2;
|
||||||
private static final int LASER_ATTACK = 3;
|
private static final int LASER_ATTACK = 3;
|
||||||
|
|
||||||
private static final int LASER_DAMAGE = 25;
|
private static final int LASER_DAMAGE = 25;
|
||||||
|
|
||||||
public CubotLaser(Cubot cubot) {
|
public CubotLaser(ControllableUnit unit) {
|
||||||
this.cubot = cubot;
|
super(null, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CubotLaser(Document document, ControllableUnit cubot) {
|
||||||
|
super(document, cubot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -49,19 +47,19 @@ public class CubotLaser extends CpuHardware {
|
|||||||
if (a == LASER_WITHDRAW) {
|
if (a == LASER_WITHDRAW) {
|
||||||
|
|
||||||
|
|
||||||
Point frontTile = cubot.getFrontTile();
|
Point frontTile = unit.getFrontTile();
|
||||||
ArrayList<GameObject> objects = cubot.getWorld().getGameObjectsBlockingAt(frontTile.x, frontTile.y);
|
ArrayList<GameObject> objects = unit.getWorld().getGameObjectsBlockingAt(frontTile.x, frontTile.y);
|
||||||
|
|
||||||
if (cubot.getCurrentAction() == Action.IDLE && objects.size() > 0) {
|
if (unit.getCurrentAction() == Action.IDLE && objects.size() > 0) {
|
||||||
//FIXME: Problem here if more than 1 object
|
//FIXME: Problem here if more than 1 object
|
||||||
if (objects.get(0) instanceof InventoryHolder) {
|
if (objects.get(0) instanceof InventoryHolder) {
|
||||||
|
|
||||||
if (((InventoryHolder) objects.get(0)).canTakeItem(b)) {
|
if (((InventoryHolder) objects.get(0)).canTakeItem(b)) {
|
||||||
if (cubot.spendEnergy(30)) {
|
if (unit.spendEnergy(30)) {
|
||||||
//Take the item
|
//Take the item
|
||||||
((InventoryHolder) objects.get(0)).takeItem(b);
|
((InventoryHolder) objects.get(0)).takeItem(b);
|
||||||
|
unit.giveItem(GameServer.INSTANCE.getRegistry().makeItem(b));
|
||||||
cubot.setHeldItem(b);
|
unit.setCurrentAction(Action.WITHDRAWING);
|
||||||
cubot.setCurrentAction(Action.WITHDRAWING);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,34 +70,23 @@ public class CubotLaser extends CpuHardware {
|
|||||||
// TODO
|
// TODO
|
||||||
} else if (a == LASER_ATTACK) {
|
} else if (a == LASER_ATTACK) {
|
||||||
|
|
||||||
if (cubot.spendEnergy(70)) {
|
if (unit.getCurrentAction() == Action.IDLE) {
|
||||||
|
if (unit.spendEnergy(70)) {
|
||||||
|
|
||||||
//Get object directly in front of the Cubot
|
//Get object directly in front of the Cubot
|
||||||
Point frontTile = cubot.getFrontTile();
|
Point frontTile = unit.getFrontTile();
|
||||||
ArrayList<GameObject> objects = cubot.getWorld().getGameObjectsAt(frontTile.x, frontTile.y);
|
ArrayList<GameObject> objects = unit.getWorld().getGameObjectsAt(frontTile.x, frontTile.y);
|
||||||
|
|
||||||
|
//todo: Add option in config to allow PvP
|
||||||
|
if (objects.size() > 0 && objects.get(0) instanceof Attackable && !(objects.get(0) instanceof Cubot)) {
|
||||||
|
((Attackable) objects.get(0)).damage(LASER_DAMAGE);
|
||||||
|
}
|
||||||
|
|
||||||
if (objects.size() > 0 && objects.get(0) instanceof Attackable) {
|
|
||||||
((Attackable) objects.get(0)).damage(LASER_DAMAGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unit.setCurrentAction(Action.ATTACKING);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BasicDBObject mongoSerialise() {
|
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
|
||||||
|
|
||||||
dbObject.put("hwid", (int) HWID);
|
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CubotLaser deserialize(DBObject obj) {
|
|
||||||
return new CubotLaser((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,16 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
import net.simon987.server.game.Action;
|
import net.simon987.server.game.objects.Action;
|
||||||
import net.simon987.server.game.Direction;
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
import net.simon987.server.io.JSONSerialisable;
|
import net.simon987.server.game.objects.Direction;
|
||||||
import org.json.simple.JSONObject;
|
import org.bson.Document;
|
||||||
|
|
||||||
public class CubotLeg extends CpuHardware implements JSONSerialisable {
|
public class CubotLeg extends HardwareModule {
|
||||||
|
|
||||||
public static final int DEFAULT_ADDRESS = 1;
|
public static final int DEFAULT_ADDRESS = 1;
|
||||||
|
|
||||||
public static final String NAME = "Cubot Leg";
|
|
||||||
|
|
||||||
private static final int LEGS_SET_DIR = 1;
|
private static final int LEGS_SET_DIR = 1;
|
||||||
private static final int LEGS_SET_DIR_AND_WALK = 2;
|
private static final int LEGS_SET_DIR_AND_WALK = 2;
|
||||||
|
|
||||||
@ -24,10 +19,12 @@ public class CubotLeg extends CpuHardware implements JSONSerialisable {
|
|||||||
*/
|
*/
|
||||||
static final char HWID = 0x0001;
|
static final char HWID = 0x0001;
|
||||||
|
|
||||||
private Cubot cubot;
|
public CubotLeg(ControllableUnit unit) {
|
||||||
|
super(null, unit);
|
||||||
|
}
|
||||||
|
|
||||||
public CubotLeg(Cubot cubot) {
|
public CubotLeg(Document document, ControllableUnit unit) {
|
||||||
this.cubot = cubot;
|
super(document, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -38,7 +35,7 @@ public class CubotLeg extends CpuHardware implements JSONSerialisable {
|
|||||||
@Override
|
@Override
|
||||||
public void handleInterrupt(Status status) {
|
public void handleInterrupt(Status status) {
|
||||||
|
|
||||||
if (cubot.getCurrentAction() == Action.IDLE) {
|
if (unit.getCurrentAction() == Action.IDLE) {
|
||||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||||
|
|
||||||
@ -48,8 +45,8 @@ public class CubotLeg extends CpuHardware implements JSONSerialisable {
|
|||||||
Direction dir = Direction.getDirection(b);
|
Direction dir = Direction.getDirection(b);
|
||||||
|
|
||||||
if (dir != null) {
|
if (dir != null) {
|
||||||
if (cubot.spendEnergy(20)) {
|
if (unit.spendEnergy(20)) {
|
||||||
cubot.setDirection(Direction.getDirection(b));
|
unit.setDirection(Direction.getDirection(b));
|
||||||
status.setErrorFlag(false);
|
status.setErrorFlag(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -59,46 +56,19 @@ public class CubotLeg extends CpuHardware implements JSONSerialisable {
|
|||||||
|
|
||||||
} else if (a == LEGS_SET_DIR_AND_WALK) {
|
} else if (a == LEGS_SET_DIR_AND_WALK) {
|
||||||
|
|
||||||
if (cubot.getMaxEnergy() >= 100) {
|
if (unit.getMaxEnergy() >= 100) {
|
||||||
Direction dir = Direction.getDirection(b);
|
Direction dir = Direction.getDirection(b);
|
||||||
|
|
||||||
if (dir != null) {
|
if (dir != null) {
|
||||||
cubot.setDirection(Direction.getDirection(b));
|
unit.setDirection(Direction.getDirection(b));
|
||||||
status.setErrorFlag(false);
|
status.setErrorFlag(false);
|
||||||
} else {
|
} else {
|
||||||
status.setErrorFlag(true);
|
status.setErrorFlag(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
cubot.setCurrentAction(Action.WALKING);
|
unit.setCurrentAction(Action.WALKING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public JSONObject serialise() {
|
|
||||||
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("hwid", (int) HWID);
|
|
||||||
json.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BasicDBObject mongoSerialise() {
|
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
|
||||||
|
|
||||||
dbObject.put("hwid", (int) HWID);
|
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CubotLeg deserialize(DBObject obj) {
|
|
||||||
return new CubotLeg((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,16 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
|
||||||
import net.simon987.server.assembly.Memory;
|
import net.simon987.server.assembly.Memory;
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
import net.simon987.server.game.World;
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
import net.simon987.server.game.pathfinding.Node;
|
import net.simon987.server.game.pathfinding.Node;
|
||||||
import net.simon987.server.game.pathfinding.Pathfinder;
|
import net.simon987.server.game.pathfinding.Pathfinder;
|
||||||
import net.simon987.server.io.JSONSerialisable;
|
import org.bson.Document;
|
||||||
import net.simon987.server.logging.LogManager;
|
|
||||||
import org.json.simple.JSONObject;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class CubotLidar extends CpuHardware implements JSONSerialisable {
|
public class CubotLidar extends HardwareModule {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hardware ID (Should be unique)
|
* Hardware ID (Should be unique)
|
||||||
@ -24,20 +19,19 @@ public class CubotLidar extends CpuHardware implements JSONSerialisable {
|
|||||||
|
|
||||||
public static final int DEFAULT_ADDRESS = 3;
|
public static final int DEFAULT_ADDRESS = 3;
|
||||||
|
|
||||||
private Cubot cubot;
|
|
||||||
|
|
||||||
private static final int LIDAR_GET_POS = 1;
|
private static final int LIDAR_GET_POS = 1;
|
||||||
private static final int LIDAR_GET_PATH = 2;
|
private static final int LIDAR_GET_PATH = 2;
|
||||||
private static final int LIDAR_GET_MAP = 3;
|
private static final int LIDAR_GET_MAP = 3;
|
||||||
private static final int LIDAR_GET_WORLD_POS = 4;
|
private static final int LIDAR_GET_WORLD_POS = 4;
|
||||||
|
private static final int LIDAR_GET_WORLD_SIZE = 5;
|
||||||
|
|
||||||
private static final int MEMORY_MAP_START = 0x0100;
|
public CubotLidar(ControllableUnit unit) {
|
||||||
private static final int MEMORY_PATH_START = 0x0000;
|
super(null, unit);
|
||||||
|
|
||||||
public CubotLidar(Cubot cubot) {
|
|
||||||
this.cubot = cubot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CubotLidar(Document document, ControllableUnit unit) {
|
||||||
|
super(document, unit);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char getId() {
|
public char getId() {
|
||||||
@ -51,23 +45,24 @@ public class CubotLidar extends CpuHardware implements JSONSerialisable {
|
|||||||
|
|
||||||
switch (a) {
|
switch (a) {
|
||||||
case LIDAR_GET_POS:
|
case LIDAR_GET_POS:
|
||||||
getCpu().getRegisterSet().getRegister("X").setValue(cubot.getX());
|
getCpu().getRegisterSet().getRegister("X").setValue(unit.getX());
|
||||||
getCpu().getRegisterSet().getRegister("Y").setValue(cubot.getY());
|
getCpu().getRegisterSet().getRegister("Y").setValue(unit.getY());
|
||||||
break;
|
break;
|
||||||
case LIDAR_GET_PATH:
|
case LIDAR_GET_PATH:
|
||||||
if (cubot.spendEnergy(50)) {
|
if (unit.spendEnergy(50)) {
|
||||||
|
int c = getCpu().getRegisterSet().getRegister("C").getValue();
|
||||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||||
int destX = getCpu().getRegisterSet().getRegister("X").getValue();
|
int destX = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
int destY = getCpu().getRegisterSet().getRegister("Y").getValue();
|
int destY = getCpu().getRegisterSet().getRegister("Y").getValue();
|
||||||
|
|
||||||
//Get path
|
//Get path
|
||||||
ArrayList<Node> nodes = Pathfinder.findPath(cubot.getWorld(), cubot.getX(), cubot.getY(),
|
ArrayList<Node> nodes = Pathfinder.findPath(unit.getWorld(), unit.getX(), unit.getY(),
|
||||||
destX, destY, b);
|
destX, destY, b);
|
||||||
|
|
||||||
//Write to memory
|
//Write to memory
|
||||||
Memory mem = getCpu().getMemory();
|
Memory mem = getCpu().getMemory();
|
||||||
|
|
||||||
int counter = MEMORY_PATH_START;
|
int counter = c;
|
||||||
|
|
||||||
if (nodes != null) {
|
if (nodes != null) {
|
||||||
|
|
||||||
@ -75,7 +70,6 @@ public class CubotLidar extends CpuHardware implements JSONSerialisable {
|
|||||||
|
|
||||||
for (Node n : nodes) {
|
for (Node n : nodes) {
|
||||||
//Store the path as a sequence of directions
|
//Store the path as a sequence of directions
|
||||||
|
|
||||||
if (lastNode == null) {
|
if (lastNode == null) {
|
||||||
lastNode = n;
|
lastNode = n;
|
||||||
continue;
|
continue;
|
||||||
@ -104,57 +98,37 @@ public class CubotLidar extends CpuHardware implements JSONSerialisable {
|
|||||||
//Indicate invalid path 0xFFFF
|
//Indicate invalid path 0xFFFF
|
||||||
mem.set(counter, 0xFFFF);
|
mem.set(counter, 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogManager.LOGGER.fine("DEBUG: path to" + destX + "," + destY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LIDAR_GET_MAP:
|
case LIDAR_GET_MAP:
|
||||||
if (cubot.spendEnergy(10)) {
|
if (unit.spendEnergy(10)) {
|
||||||
char[][] mapInfo = cubot.getWorld().getMapInfo();
|
char[][] mapInfo = unit.getWorld().getMapInfo();
|
||||||
|
|
||||||
int i = MEMORY_MAP_START;
|
//Write map data to the location specified by register X
|
||||||
for (int y = 0; y < World.WORLD_SIZE; y++) {
|
int i = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
for (int x = 0; x < World.WORLD_SIZE; x++) {
|
for (int y = 0; y < unit.getWorld().getWorldSize(); y++) {
|
||||||
|
for (int x = 0; x < unit.getWorld().getWorldSize(); x++) {
|
||||||
getCpu().getMemory().set(i++, mapInfo[x][y]);
|
getCpu().getMemory().set(i++, mapInfo[x][y]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LIDAR_GET_WORLD_SIZE:
|
||||||
|
getCpu().getRegisterSet().getRegister("X").setValue(unit.getWorld().getWorldSize());
|
||||||
|
getCpu().getRegisterSet().getRegister("Y").setValue(unit.getWorld().getWorldSize());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LIDAR_GET_WORLD_POS:
|
case LIDAR_GET_WORLD_POS:
|
||||||
getCpu().getRegisterSet().getRegister("X").setValue(cubot.getWorld().getX());
|
getCpu().getRegisterSet().getRegister("X").setValue(unit.getWorld().getX());
|
||||||
getCpu().getRegisterSet().getRegister("Y").setValue(cubot.getWorld().getY());
|
getCpu().getRegisterSet().getRegister("Y").setValue(unit.getWorld().getY());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JSONObject serialise() {
|
|
||||||
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("hwid", (int) HWID);
|
|
||||||
json.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BasicDBObject mongoSerialise() {
|
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
|
||||||
|
|
||||||
dbObject.put("hwid", (int) HWID);
|
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CubotLidar deserialize(DBObject obj) {
|
|
||||||
return new CubotLidar((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,67 +1,44 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
import net.simon987.cubotplugin.event.*;
|
||||||
import net.simon987.cubotplugin.event.CpuInitialisationListener;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.cubotplugin.event.UserCreationListener;
|
import net.simon987.server.game.objects.GameRegistry;
|
||||||
import net.simon987.server.ServerConfiguration;
|
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
|
||||||
import net.simon987.server.game.GameObject;
|
|
||||||
import net.simon987.server.io.CpuHardwareDeserializer;
|
|
||||||
import net.simon987.server.io.GameObjectDeserializer;
|
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import net.simon987.server.plugin.ServerPlugin;
|
import net.simon987.server.plugin.ServerPlugin;
|
||||||
|
|
||||||
public class CubotPlugin extends ServerPlugin implements GameObjectDeserializer, CpuHardwareDeserializer {
|
public class CubotPlugin extends ServerPlugin {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServerConfiguration config) {
|
public void init(GameServer gameServer) {
|
||||||
listeners.add(new CpuInitialisationListener());
|
listeners.add(new CpuInitialisationListener());
|
||||||
listeners.add(new UserCreationListener());
|
listeners.add(new UserCreationListener());
|
||||||
|
//Debug commands
|
||||||
|
listeners.add(new ChargeShieldCommandListener());
|
||||||
|
listeners.add(new SetInventoryPosition());
|
||||||
|
listeners.add(new PutItemCommandListener());
|
||||||
|
listeners.add(new PopItemCommandListener());
|
||||||
|
//Leaderboard
|
||||||
|
listeners.add(new DeathListener());
|
||||||
|
listeners.add(new WalkListener());
|
||||||
|
|
||||||
LogManager.LOGGER.info("Initialised Cubot plugin");
|
GameRegistry registry = gameServer.getRegistry();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
registry.registerGameObject(Cubot.class);
|
||||||
public GameObject deserializeObject(DBObject object) {
|
|
||||||
|
|
||||||
int objType = (int) object.get("t");
|
registry.registerHardware(CubotLeg.class);
|
||||||
|
registry.registerHardware(CubotLaser.class);
|
||||||
|
registry.registerHardware(CubotLidar.class);
|
||||||
|
registry.registerHardware(CubotDrill.class);
|
||||||
|
registry.registerHardware(CubotInventory.class);
|
||||||
|
registry.registerHardware(CubotKeyboard.class);
|
||||||
|
registry.registerHardware(CubotHologram.class);
|
||||||
|
registry.registerHardware(CubotBattery.class);
|
||||||
|
registry.registerHardware(CubotFloppyDrive.class);
|
||||||
|
registry.registerHardware(CubotComPort.class);
|
||||||
|
registry.registerHardware(CubotShield.class);
|
||||||
|
registry.registerHardware(CubotCore.class);
|
||||||
|
|
||||||
if (objType == Cubot.ID) {
|
LogManager.LOGGER.info("(Cubot Plugin) Initialised Cubot plugin");
|
||||||
|
|
||||||
return Cubot.deserialize(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CpuHardware deserializeHardware(DBObject obj) {
|
|
||||||
int hwid = (int) obj.get("hwid");
|
|
||||||
|
|
||||||
switch (hwid) {
|
|
||||||
case CubotLeg.HWID:
|
|
||||||
return CubotLeg.deserialize(obj);
|
|
||||||
case CubotLaser.HWID:
|
|
||||||
return CubotLaser.deserialize(obj);
|
|
||||||
case CubotLidar.HWID:
|
|
||||||
return CubotLidar.deserialize(obj);
|
|
||||||
case CubotDrill.HWID:
|
|
||||||
return CubotDrill.deserialize(obj);
|
|
||||||
case CubotInventory.HWID:
|
|
||||||
return CubotInventory.deserialize(obj);
|
|
||||||
case CubotKeyboard.HWID:
|
|
||||||
return CubotKeyboard.deserialize(obj);
|
|
||||||
case CubotHologram.HWID:
|
|
||||||
return CubotHologram.deserialize(obj);
|
|
||||||
case CubotBattery.HWID:
|
|
||||||
return CubotBattery.deserialize(obj);
|
|
||||||
case CubotFloppyDrive.HWID:
|
|
||||||
return CubotFloppyDrive.deserialize(obj);
|
|
||||||
case CubotComPort.HWID:
|
|
||||||
return CubotComPort.deserialize(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
public class CubotShield extends CubotHardwareModule {
|
||||||
|
|
||||||
|
public static final char DEFAULT_ADDRESS = 0x000F;
|
||||||
|
|
||||||
|
static final char HWID = 0x000F;
|
||||||
|
|
||||||
|
private static final int SHIELD_CHARGE = 1;
|
||||||
|
private static final int SHIELD_POLL = 2;
|
||||||
|
|
||||||
|
public static final int COST = GameServer.INSTANCE.getConfig().getInt("shield_energy_cost");
|
||||||
|
|
||||||
|
public CubotShield(Cubot cubot) {
|
||||||
|
super(cubot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CubotShield(Document document, ControllableUnit cubot) {
|
||||||
|
super(document, cubot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getId() {
|
||||||
|
return HWID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleInterrupt(Status status) {
|
||||||
|
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||||
|
// b = amount to charge
|
||||||
|
if(a == SHIELD_CHARGE) {
|
||||||
|
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||||
|
cubot.chargeShield(b);
|
||||||
|
} else if (a == SHIELD_POLL) {
|
||||||
|
int shield = cubot.getShield();
|
||||||
|
getCpu().getRegisterSet().getRegister("B").setValue(shield);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status of a Cubot (Special buff or debuff)
|
||||||
|
*/
|
||||||
|
public enum CubotStatus {
|
||||||
|
|
||||||
|
DEFAULT(0),
|
||||||
|
RADIATED(1),
|
||||||
|
DAMAGED(2),
|
||||||
|
FACTORY_NEW(3);
|
||||||
|
|
||||||
|
public char val;
|
||||||
|
|
||||||
|
CubotStatus(int val) {
|
||||||
|
this.val = (char) val;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,17 +1,16 @@
|
|||||||
package net.simon987.cubotplugin;
|
package net.simon987.cubotplugin;
|
||||||
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.assembly.Memory;
|
import net.simon987.server.assembly.Memory;
|
||||||
import net.simon987.server.io.MongoSerialisable;
|
import net.simon987.server.io.MongoSerializable;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a floppy disk that is inside a floppy drive.
|
* Represents a floppy disk that is inside a floppy drive.
|
||||||
* Floppies contains 80 tracks with 18 sectors per track.
|
* Floppies contains 80 tracks with 18 sectors per track.
|
||||||
* That's 1440 sectors of 512 words. (total 1,474,560 bytes / 737,280 words / 1.44Mb)
|
* That's 1440 sectors of 512 words. (total 1,474,560 bytes / 737,280 words / 1.44Mb)
|
||||||
*/
|
*/
|
||||||
public class FloppyDisk implements MongoSerialisable {
|
public class FloppyDisk implements MongoSerializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contents of the disk
|
* Contents of the disk
|
||||||
@ -29,6 +28,11 @@ public class FloppyDisk implements MongoSerialisable {
|
|||||||
this.memory = new Memory(512 * 1440);
|
this.memory = new Memory(512 * 1440);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FloppyDisk(Document document) {
|
||||||
|
this.rwHeadTrack = document.getInteger("rwHeadTrack");
|
||||||
|
this.memory = new Memory((Document) document.get("memory"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read 512 words from the specified sector to cpu memory at specified address
|
* Read 512 words from the specified sector to cpu memory at specified address
|
||||||
*
|
*
|
||||||
@ -84,8 +88,8 @@ public class FloppyDisk implements MongoSerialisable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public Document mongoSerialise() {
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
Document dbObject = new Document();
|
||||||
|
|
||||||
dbObject.put("rwHeadTrack", rwHeadTrack);
|
dbObject.put("rwHeadTrack", rwHeadTrack);
|
||||||
dbObject.put("memory", memory.mongoSerialise());
|
dbObject.put("memory", memory.mongoSerialise());
|
||||||
@ -93,16 +97,6 @@ public class FloppyDisk implements MongoSerialisable {
|
|||||||
return dbObject;
|
return dbObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FloppyDisk deserialise(DBObject obj) {
|
|
||||||
|
|
||||||
FloppyDisk floppyDisk = new FloppyDisk();
|
|
||||||
|
|
||||||
floppyDisk.rwHeadTrack = (int) obj.get("rwHeadTrack");
|
|
||||||
floppyDisk.memory = Memory.deserialize((DBObject) obj.get("memory"));
|
|
||||||
|
|
||||||
return floppyDisk;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Memory getMemory() {
|
public Memory getMemory() {
|
||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
package net.simon987.cubotplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.cubotplugin.Cubot;
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.event.DebugCommandEvent;
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.event.GameEventListener;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug command to add shield points to a Cubot
|
||||||
|
*/
|
||||||
|
public class ChargeShieldCommandListener implements GameEventListener {
|
||||||
|
@Override
|
||||||
|
public Class getListenedEventType() {
|
||||||
|
return DebugCommandEvent.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(GameEvent event) {
|
||||||
|
|
||||||
|
DebugCommandEvent e = (DebugCommandEvent) event;
|
||||||
|
|
||||||
|
if (e.getName().equals("chargeShield")) {
|
||||||
|
|
||||||
|
GameObject cubot = GameServer.INSTANCE.getGameUniverse().getObject(e.getObjectId("objectId"));
|
||||||
|
|
||||||
|
if (cubot != null) {
|
||||||
|
|
||||||
|
if (cubot instanceof Cubot) {
|
||||||
|
|
||||||
|
String hp = ((Cubot) cubot).getHp() + "/" + ((Cubot) cubot).getMaxHp();
|
||||||
|
int oldShield = ((Cubot) cubot).getShield();
|
||||||
|
((Cubot) cubot).chargeShield(e.getInt("amount"));
|
||||||
|
|
||||||
|
e.reply("Success: " + hp + " (" + oldShield + ") -> " + hp + "(" + ((Cubot) cubot).getShield() +
|
||||||
|
")");
|
||||||
|
} else {
|
||||||
|
e.reply("Object is not a Cubot");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
e.reply("Object not found: " + e.getLong("objectId"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,7 +5,6 @@ import net.simon987.server.assembly.CPU;
|
|||||||
import net.simon987.server.event.CpuInitialisationEvent;
|
import net.simon987.server.event.CpuInitialisationEvent;
|
||||||
import net.simon987.server.event.GameEvent;
|
import net.simon987.server.event.GameEvent;
|
||||||
import net.simon987.server.event.GameEventListener;
|
import net.simon987.server.event.GameEventListener;
|
||||||
import net.simon987.server.user.User;
|
|
||||||
|
|
||||||
public class CpuInitialisationListener implements GameEventListener {
|
public class CpuInitialisationListener implements GameEventListener {
|
||||||
@Override
|
@Override
|
||||||
@ -15,42 +14,48 @@ public class CpuInitialisationListener implements GameEventListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(GameEvent event) {
|
public void handle(GameEvent event) {
|
||||||
//LogManager.LOGGER.fine("(Plugin) Handled CPU Initialisation event (Cubot Plugin)");
|
|
||||||
|
|
||||||
CPU cpu = (CPU) event.getSource();
|
CPU cpu = (CPU) event.getSource();
|
||||||
User user = ((CpuInitialisationEvent) event).getUser();
|
Cubot cubot = (Cubot) ((CpuInitialisationEvent) event).getUnit();
|
||||||
|
cpu.setHardwareHost(cubot);
|
||||||
|
|
||||||
CubotLeg legHw = new CubotLeg((Cubot) user.getControlledUnit());
|
CubotLeg legHw = new CubotLeg(cubot);
|
||||||
legHw.setCpu(cpu);
|
legHw.setCpu(cpu);
|
||||||
CubotLaser laserHw = new CubotLaser((Cubot) user.getControlledUnit());
|
CubotLaser laserHw = new CubotLaser(cubot);
|
||||||
laserHw.setCpu(cpu);
|
laserHw.setCpu(cpu);
|
||||||
CubotLidar radarHw = new CubotLidar((Cubot) user.getControlledUnit());
|
CubotLidar radarHw = new CubotLidar(cubot);
|
||||||
radarHw.setCpu(cpu);
|
radarHw.setCpu(cpu);
|
||||||
CubotKeyboard keyboard = new CubotKeyboard((Cubot) user.getControlledUnit());
|
CubotKeyboard keyboard = new CubotKeyboard(cubot);
|
||||||
keyboard.setCpu(cpu);
|
keyboard.setCpu(cpu);
|
||||||
CubotDrill drillHw = new CubotDrill((Cubot) user.getControlledUnit());
|
CubotDrill drillHw = new CubotDrill(cubot);
|
||||||
drillHw.setCpu(cpu);
|
drillHw.setCpu(cpu);
|
||||||
CubotInventory invHw = new CubotInventory((Cubot) user.getControlledUnit());
|
CubotInventory invHw = new CubotInventory(cubot);
|
||||||
invHw.setCpu(cpu);
|
invHw.setCpu(cpu);
|
||||||
CubotHologram emoteHw = new CubotHologram((Cubot) user.getControlledUnit());
|
CubotHologram emoteHw = new CubotHologram(cubot);
|
||||||
emoteHw.setCpu(cpu);
|
emoteHw.setCpu(cpu);
|
||||||
CubotBattery batteryHw = new CubotBattery((Cubot) user.getControlledUnit());
|
CubotBattery batteryHw = new CubotBattery(cubot);
|
||||||
batteryHw.setCpu(cpu);
|
batteryHw.setCpu(cpu);
|
||||||
CubotFloppyDrive floppyHw = new CubotFloppyDrive((Cubot) user.getControlledUnit());
|
CubotFloppyDrive floppyHw = new CubotFloppyDrive(cubot);
|
||||||
floppyHw.setCpu(cpu);
|
floppyHw.setCpu(cpu);
|
||||||
CubotComPort comPortHw = new CubotComPort((Cubot) user.getControlledUnit());
|
CubotComPort comPortHw = new CubotComPort(cubot);
|
||||||
comPortHw.setCpu(cpu);
|
comPortHw.setCpu(cpu);
|
||||||
|
CubotCore coreHw = new CubotCore(cubot);
|
||||||
|
coreHw.setCpu(cpu);
|
||||||
|
CubotShield shieldHw = new CubotShield(cubot);
|
||||||
|
shieldHw.setCpu(cpu);
|
||||||
|
|
||||||
cpu.attachHardware(legHw, CubotLeg.DEFAULT_ADDRESS);
|
cubot.attachHardware(legHw, CubotLeg.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(laserHw, CubotLaser.DEFAULT_ADDRESS);
|
cubot.attachHardware(laserHw, CubotLaser.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(radarHw, CubotLidar.DEFAULT_ADDRESS);
|
cubot.attachHardware(radarHw, CubotLidar.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(keyboard, CubotKeyboard.DEFAULT_ADDRESS);
|
cubot.attachHardware(keyboard, CubotKeyboard.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(drillHw, CubotDrill.DEFAULT_ADDRESS);
|
cubot.attachHardware(drillHw, CubotDrill.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(invHw, CubotInventory.DEFAULT_ADDRESS);
|
cubot.attachHardware(invHw, CubotInventory.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(invHw, CubotInventory.DEFAULT_ADDRESS);
|
cubot.attachHardware(invHw, CubotInventory.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(emoteHw, CubotHologram.DEFAULT_ADDRESS);
|
cubot.attachHardware(emoteHw, CubotHologram.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(batteryHw, CubotBattery.DEFAULT_ADDRESS);
|
cubot.attachHardware(batteryHw, CubotBattery.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(floppyHw, CubotFloppyDrive.DEFAULT_ADDRESS);
|
cubot.attachHardware(floppyHw, CubotFloppyDrive.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(comPortHw, CubotComPort.DEFAULT_ADDRESS);
|
cubot.attachHardware(comPortHw, CubotComPort.DEFAULT_ADDRESS);
|
||||||
|
cubot.attachHardware(coreHw, CubotCore.DEFAULT_ADDRESS);
|
||||||
|
cubot.attachHardware(shieldHw, CubotShield.DEFAULT_ADDRESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package net.simon987.cubotplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.cubotplugin.Cubot;
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
|
||||||
|
public class CubotWalkEvent extends GameEvent {
|
||||||
|
|
||||||
|
public CubotWalkEvent(Cubot cubot) {
|
||||||
|
setSource(cubot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cubot getSource() {
|
||||||
|
return (Cubot) super.getSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package net.simon987.cubotplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
|
||||||
|
public class DeathEvent extends GameEvent {
|
||||||
|
|
||||||
|
public DeathEvent(GameObject object) {
|
||||||
|
setSource(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GameObject getSource() {
|
||||||
|
return (GameObject) super.getSource();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package net.simon987.cubotplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.event.GameEventListener;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
|
||||||
|
public class DeathListener implements GameEventListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getListenedEventType() {
|
||||||
|
return DeathEvent.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(GameEvent event) {
|
||||||
|
DeathEvent DeathEvent = (DeathEvent) event;
|
||||||
|
GameObject object = DeathEvent.getSource();
|
||||||
|
if (object instanceof ControllableUnit) {
|
||||||
|
((ControllableUnit) object).getParent().getStats().incrementStat("death", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package net.simon987.cubotplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.cubotplugin.Cubot;
|
||||||
|
import net.simon987.cubotplugin.CubotInventory;
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.event.DebugCommandEvent;
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.event.GameEventListener;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
|
||||||
|
public class PopItemCommandListener implements GameEventListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getListenedEventType() {
|
||||||
|
return DebugCommandEvent.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(GameEvent event) {
|
||||||
|
|
||||||
|
DebugCommandEvent e = (DebugCommandEvent) event;
|
||||||
|
|
||||||
|
if (e.getName().equals("clearItem")) {
|
||||||
|
|
||||||
|
GameObject object = GameServer.INSTANCE.getGameUniverse().getObject(e.getObjectId("objectId"));
|
||||||
|
|
||||||
|
if (object != null) {
|
||||||
|
|
||||||
|
if (object instanceof Cubot) {
|
||||||
|
|
||||||
|
CubotInventory inventory = (CubotInventory) ((Cubot) object).getHardware(CubotInventory.class);
|
||||||
|
|
||||||
|
e.reply("Removed item from inventory: " + inventory.clearItem());
|
||||||
|
} else {
|
||||||
|
e.reply("Object is not a Cubot");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
e.reply("Object not found: " + e.getLong("objectId"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package net.simon987.cubotplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.cubotplugin.Cubot;
|
||||||
|
import net.simon987.cubotplugin.CubotInventory;
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.event.DebugCommandEvent;
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.event.GameEventListener;
|
||||||
|
import net.simon987.server.game.item.Item;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
public class PutItemCommandListener implements GameEventListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getListenedEventType() {
|
||||||
|
return DebugCommandEvent.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(GameEvent event) {
|
||||||
|
|
||||||
|
DebugCommandEvent e = (DebugCommandEvent) event;
|
||||||
|
|
||||||
|
if (e.getName().equals("putItem")) {
|
||||||
|
|
||||||
|
GameObject object = GameServer.INSTANCE.getGameUniverse().getObject(e.getObjectId("objectId"));
|
||||||
|
|
||||||
|
if (object != null) {
|
||||||
|
|
||||||
|
if (object instanceof Cubot) {
|
||||||
|
|
||||||
|
CubotInventory inventory = (CubotInventory) ((Cubot) object).getHardware(CubotInventory.class);
|
||||||
|
Item item = GameServer.INSTANCE.getRegistry().deserializeItem(Document.parse(e.getString("item")));
|
||||||
|
|
||||||
|
if (item != null) {
|
||||||
|
inventory.putItem(item);
|
||||||
|
e.reply("Set item to " + item.getClass().getSimpleName());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
e.reply("Couldn't deserialize item");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
e.reply("Object is not a Cubot");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
e.reply("Object not found: " + e.getLong("objectId"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package net.simon987.cubotplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.cubotplugin.Cubot;
|
||||||
|
import net.simon987.cubotplugin.CubotInventory;
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.event.DebugCommandEvent;
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.event.GameEventListener;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
|
||||||
|
public class SetInventoryPosition implements GameEventListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getListenedEventType() {
|
||||||
|
return DebugCommandEvent.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(GameEvent event) {
|
||||||
|
|
||||||
|
DebugCommandEvent e = (DebugCommandEvent) event;
|
||||||
|
|
||||||
|
if (e.getName().equals("setInventoryPosition")) {
|
||||||
|
|
||||||
|
GameObject object = GameServer.INSTANCE.getGameUniverse().getObject(e.getObjectId("objectId"));
|
||||||
|
|
||||||
|
if (object != null) {
|
||||||
|
|
||||||
|
if (object instanceof Cubot) {
|
||||||
|
|
||||||
|
int position = e.getInt("position");
|
||||||
|
CubotInventory inventory = (CubotInventory) ((Cubot) object).getHardware(CubotInventory.class);
|
||||||
|
|
||||||
|
inventory.setPosition(position);
|
||||||
|
e.reply("Set inventory position to " + position);
|
||||||
|
} else {
|
||||||
|
e.reply("Object is not a Cubot");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
e.reply("Object not found: " + e.getLong("objectId"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,19 @@
|
|||||||
package net.simon987.cubotplugin.event;
|
package net.simon987.cubotplugin.event;
|
||||||
|
|
||||||
import net.simon987.cubotplugin.Cubot;
|
import net.simon987.cubotplugin.Cubot;
|
||||||
|
import net.simon987.cubotplugin.CubotStatus;
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.IServerConfiguration;
|
||||||
|
import net.simon987.server.assembly.Assembler;
|
||||||
|
import net.simon987.server.assembly.AssemblyResult;
|
||||||
|
import net.simon987.server.assembly.CPU;
|
||||||
|
import net.simon987.server.assembly.exception.CancelledException;
|
||||||
import net.simon987.server.event.GameEvent;
|
import net.simon987.server.event.GameEvent;
|
||||||
import net.simon987.server.event.GameEventListener;
|
import net.simon987.server.event.GameEventListener;
|
||||||
import net.simon987.server.event.UserCreationEvent;
|
import net.simon987.server.event.UserCreationEvent;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import net.simon987.server.user.User;
|
import net.simon987.server.user.User;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@ -24,13 +31,16 @@ public class UserCreationListener implements GameEventListener {
|
|||||||
|
|
||||||
User user = (User) event.getSource();
|
User user = (User) event.getSource();
|
||||||
Cubot cubot = new Cubot();
|
Cubot cubot = new Cubot();
|
||||||
cubot.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
cubot.addStatus(CubotStatus.FACTORY_NEW);
|
||||||
|
cubot.setObjectId(new ObjectId());
|
||||||
|
IServerConfiguration config = GameServer.INSTANCE.getConfig();
|
||||||
|
|
||||||
Point point = null;
|
Point point = null;
|
||||||
while (point == null || cubot.getWorld() == null) {
|
while (point == null || cubot.getWorld() == null) {
|
||||||
int spawnX = GameServer.INSTANCE.getConfig().getInt("new_user_worldX") + random.nextInt(5);
|
int spawnX = config.getInt("new_user_worldX") + random.nextInt(5);
|
||||||
int spawnY = GameServer.INSTANCE.getConfig().getInt("new_user_worldY") + random.nextInt(5);
|
int spawnY = config.getInt("new_user_worldY") + random.nextInt(5);
|
||||||
cubot.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(spawnX, spawnY, true));
|
String dimension = config.getString("new_user_dimension");
|
||||||
|
cubot.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(spawnX, spawnY, true, dimension));
|
||||||
|
|
||||||
point = cubot.getWorld().getRandomPassableTile();
|
point = cubot.getWorld().getRandomPassableTile();
|
||||||
}
|
}
|
||||||
@ -40,15 +50,34 @@ public class UserCreationListener implements GameEventListener {
|
|||||||
cubot.getWorld().addObject(cubot);
|
cubot.getWorld().addObject(cubot);
|
||||||
cubot.getWorld().incUpdatable();
|
cubot.getWorld().incUpdatable();
|
||||||
|
|
||||||
cubot.setHeldItem(GameServer.INSTANCE.getConfig().getInt("new_user_item"));
|
|
||||||
cubot.setEnergy(GameServer.INSTANCE.getConfig().getInt("battery_max_energy"));
|
|
||||||
cubot.setMaxEnergy(GameServer.INSTANCE.getConfig().getInt("battery_max_energy"));
|
|
||||||
|
|
||||||
cubot.setParent(user);
|
cubot.setParent(user);
|
||||||
user.setControlledUnit(cubot);
|
user.setControlledUnit(cubot);
|
||||||
|
|
||||||
|
//Create CPU
|
||||||
|
try {
|
||||||
|
cubot.setCpu(new CPU(GameServer.INSTANCE.getConfig(), cubot));
|
||||||
|
cubot.getCpu().setHardwareHost(cubot);
|
||||||
|
user.setUserCode(config.getString("new_user_code"));
|
||||||
|
|
||||||
|
//Compile user code
|
||||||
|
AssemblyResult ar = new Assembler(cubot.getCpu().getInstructionSet(), cubot.getCpu().getRegisterSet(),
|
||||||
|
GameServer.INSTANCE.getConfig()).parse(user.getUserCode());
|
||||||
|
|
||||||
|
cubot.getCpu().getMemory().clear();
|
||||||
|
|
||||||
|
//Write assembled code to mem
|
||||||
|
char[] assembledCode = ar.getWords();
|
||||||
|
|
||||||
|
cubot.getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length);
|
||||||
|
cubot.getCpu().setCodeSectionOffset(ar.getCodeSectionOffset());
|
||||||
|
} catch (CancelledException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
cubot.setHp(config.getInt("cubot_max_hp"));
|
||||||
|
cubot.setMaxHp(config.getInt("cubot_max_hp"));
|
||||||
|
cubot.setMaxShield(config.getInt("cubot_max_shield"));
|
||||||
|
|
||||||
LogManager.LOGGER.fine("(Plugin) Handled User creation event (Cubot Plugin)");
|
LogManager.LOGGER.fine("(Plugin) Handled User creation event (Cubot Plugin)");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package net.simon987.cubotplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.event.GameEventListener;
|
||||||
|
|
||||||
|
public class WalkListener implements GameEventListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getListenedEventType() {
|
||||||
|
return CubotWalkEvent.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(GameEvent event) {
|
||||||
|
CubotWalkEvent walkEvent = (CubotWalkEvent) event;
|
||||||
|
walkEvent.getSource().getParent().getStats().incrementStat("walkDistance", 1);
|
||||||
|
}
|
||||||
|
}
|
@ -3,17 +3,10 @@ package net.simon987.cubotplugin;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
public class CubotTest {
|
public class CubotTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test(){
|
public void test(){
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
assertEquals(1, 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="Spring" name="Spring">
|
||||||
|
<configuration />
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
@ -12,11 +17,40 @@
|
|||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="module" module-name="Server" />
|
<orderEntry type="module" module-name="Server" />
|
||||||
<orderEntry type="library" name="Maven: org.java-websocket:Java-WebSocket:1.3.6" level="project" />
|
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.6" level="project" />
|
||||||
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.42" level="project" />
|
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-sync:3.9.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:bson:3.9.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:2.10.1" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-core:3.9.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.1.5.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.8.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.sparkjava:spark-template-velocity:2.7.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.25" level="project" />
|
||||||
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
|
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
||||||
|
@ -7,18 +7,18 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.simon987.server</groupId>
|
<groupId>net.simon987.server</groupId>
|
||||||
<artifactId>server_root</artifactId>
|
<artifactId>server_root</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.simon987.pluginmischw</groupId>
|
<groupId>net.simon987.pluginmischw</groupId>
|
||||||
<artifactId>plugin-misc-hw</artifactId>
|
<artifactId>plugin-misc-hw</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.simon987.server</groupId>
|
<groupId>net.simon987.server</groupId>
|
||||||
<artifactId>server</artifactId>
|
<artifactId>server</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -1,17 +1,29 @@
|
|||||||
package net.simon987.mischwplugin;
|
package net.simon987.mischwplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
import net.simon987.server.assembly.Util;
|
import net.simon987.server.assembly.Util;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
public class Clock extends CpuHardware {
|
/**
|
||||||
|
* Hardware to get game time
|
||||||
|
*/
|
||||||
|
public class Clock extends HardwareModule {
|
||||||
|
|
||||||
public static final char HWID = 0x0008;
|
private static final char HWID = 0x0008;
|
||||||
|
|
||||||
public static final char DEFAULT_ADDRESS = 0x0008;
|
public static final char DEFAULT_ADDRESS = 0x0008;
|
||||||
|
|
||||||
|
public Clock() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Clock(Document document, ControllableUnit unit) {
|
||||||
|
super(document, unit);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInterrupt(Status status) {
|
public void handleInterrupt(Status status) {
|
||||||
|
|
||||||
@ -28,17 +40,12 @@ public class Clock extends CpuHardware {
|
|||||||
return HWID;
|
return HWID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Clock deserialize() {
|
|
||||||
return new Clock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public Document mongoSerialise() {
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
Document dbObject = new Document();
|
||||||
|
dbObject.put("type", getClass().getCanonicalName());
|
||||||
dbObject.put("hwid", (int) HWID);
|
|
||||||
|
|
||||||
return dbObject;
|
return dbObject;
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,26 @@
|
|||||||
package net.simon987.mischwplugin;
|
package net.simon987.mischwplugin;
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.mischwplugin.event.CpuInitialisationListener;
|
import net.simon987.mischwplugin.event.CpuInitialisationListener;
|
||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
import net.simon987.server.game.objects.GameRegistry;
|
||||||
import net.simon987.server.io.CpuHardwareDeserializer;
|
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import net.simon987.server.plugin.ServerPlugin;
|
import net.simon987.server.plugin.ServerPlugin;
|
||||||
|
|
||||||
public class MiscHWPlugin extends ServerPlugin implements CpuHardwareDeserializer {
|
/**
|
||||||
|
* Plugin that adds miscellaneous hardware to the game
|
||||||
|
*/
|
||||||
|
public class MiscHWPlugin extends ServerPlugin {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServerConfiguration config) {
|
public void init(GameServer gameServer) {
|
||||||
listeners.add(new CpuInitialisationListener());
|
listeners.add(new CpuInitialisationListener());
|
||||||
|
|
||||||
LogManager.LOGGER.info("Initialised Misc Hardware Plugin");
|
GameRegistry registry = gameServer.getRegistry();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
registry.registerHardware(RandomNumberGenerator.class);
|
||||||
public CpuHardware deserializeHardware(DBObject hwJson) {
|
registry.registerHardware(Clock.class);
|
||||||
int hwid = (int) hwJson.get("hwid");
|
|
||||||
|
|
||||||
switch (hwid) {
|
LogManager.LOGGER.info("(Mist HW Plugin) Initialised Misc Hardware Plugin");
|
||||||
case RandomNumberGenerator.HWID:
|
|
||||||
return RandomNumberGenerator.deserialize();
|
|
||||||
case Clock.HWID:
|
|
||||||
return Clock.deserialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
package net.simon987.mischwplugin;
|
package net.simon987.mischwplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class RandomNumberGenerator extends CpuHardware {
|
/**
|
||||||
|
* Hardware to generate random numbers
|
||||||
|
*/
|
||||||
|
public class RandomNumberGenerator extends HardwareModule {
|
||||||
|
|
||||||
public static final char HWID = 0x0007;
|
private static final char HWID = 0x0007;
|
||||||
|
|
||||||
public static final char DEFAULT_ADDRESS = 0x0007;
|
public static final char DEFAULT_ADDRESS = 0x0007;
|
||||||
|
|
||||||
@ -18,6 +22,11 @@ public class RandomNumberGenerator extends CpuHardware {
|
|||||||
random = new Random();
|
random = new Random();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RandomNumberGenerator(Document document, ControllableUnit unit) {
|
||||||
|
super(document, unit);
|
||||||
|
random = new Random();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInterrupt(Status status) {
|
public void handleInterrupt(Status status) {
|
||||||
|
|
||||||
@ -31,16 +40,11 @@ public class RandomNumberGenerator extends CpuHardware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public Document mongoSerialise() {
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
Document dbObject = new Document();
|
||||||
|
dbObject.put("type", getClass().getCanonicalName());
|
||||||
dbObject.put("hwid", (int) HWID);
|
|
||||||
|
|
||||||
return dbObject;
|
return dbObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RandomNumberGenerator deserialize() {
|
|
||||||
return new RandomNumberGenerator();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import net.simon987.server.assembly.CPU;
|
|||||||
import net.simon987.server.event.CpuInitialisationEvent;
|
import net.simon987.server.event.CpuInitialisationEvent;
|
||||||
import net.simon987.server.event.GameEvent;
|
import net.simon987.server.event.GameEvent;
|
||||||
import net.simon987.server.event.GameEventListener;
|
import net.simon987.server.event.GameEventListener;
|
||||||
|
import net.simon987.server.game.objects.HardwareHost;
|
||||||
|
|
||||||
public class CpuInitialisationListener implements GameEventListener {
|
public class CpuInitialisationListener implements GameEventListener {
|
||||||
|
|
||||||
@ -18,13 +19,15 @@ public class CpuInitialisationListener implements GameEventListener {
|
|||||||
public void handle(GameEvent event) {
|
public void handle(GameEvent event) {
|
||||||
|
|
||||||
CPU cpu = (CPU) event.getSource();
|
CPU cpu = (CPU) event.getSource();
|
||||||
|
HardwareHost cubot = (HardwareHost) ((CpuInitialisationEvent) event).getUnit();
|
||||||
|
cpu.setHardwareHost(cubot);
|
||||||
|
|
||||||
RandomNumberGenerator rngHW = new RandomNumberGenerator();
|
RandomNumberGenerator rngHW = new RandomNumberGenerator();
|
||||||
rngHW.setCpu(cpu);
|
rngHW.setCpu(cpu);
|
||||||
Clock clock = new Clock();
|
Clock clock = new Clock();
|
||||||
clock.setCpu(cpu);
|
clock.setCpu(cpu);
|
||||||
|
|
||||||
cpu.attachHardware(rngHW, RandomNumberGenerator.DEFAULT_ADDRESS);
|
cpu.getHardwareHost().attachHardware(rngHW, RandomNumberGenerator.DEFAULT_ADDRESS);
|
||||||
cpu.attachHardware(clock, Clock.DEFAULT_ADDRESS);
|
cpu.getHardwareHost().attachHardware(clock, Clock.DEFAULT_ADDRESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="Spring" name="Spring">
|
||||||
|
<configuration />
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
@ -15,10 +20,39 @@
|
|||||||
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
|
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
||||||
<orderEntry type="module" module-name="Server" />
|
<orderEntry type="module" module-name="Server" />
|
||||||
<orderEntry type="library" name="Maven: org.java-websocket:Java-WebSocket:1.3.6" level="project" />
|
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.6" level="project" />
|
||||||
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.42" level="project" />
|
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-sync:3.9.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:bson:3.9.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:2.10.1" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-core:3.9.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.1.5.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.8.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.sparkjava:spark-template-velocity:2.7.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.25" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
@ -7,12 +7,12 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.simon987.server</groupId>
|
<groupId>net.simon987.server</groupId>
|
||||||
<artifactId>server_root</artifactId>
|
<artifactId>server_root</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.simon987.pluginnpc</groupId>
|
<groupId>net.simon987.pluginnpc</groupId>
|
||||||
<artifactId>plugin-npc</artifactId>
|
<artifactId>plugin-npc</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -25,7 +25,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.simon987.server</groupId>
|
<groupId>net.simon987.server</groupId>
|
||||||
<artifactId>server</artifactId>
|
<artifactId>server</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
162
Plugin NPC/src/main/java/net/simon987/npcplugin/ElectricBox.java
Normal file
162
Plugin NPC/src/main/java/net/simon987/npcplugin/ElectricBox.java
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.assembly.Util;
|
||||||
|
import net.simon987.server.game.objects.Attackable;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
import net.simon987.server.game.objects.Rechargeable;
|
||||||
|
import net.simon987.server.game.objects.Updatable;
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Game object that deals damage to nearby objects and gives them energy
|
||||||
|
*/
|
||||||
|
public class ElectricBox extends GameObject implements Updatable, Attackable {
|
||||||
|
|
||||||
|
private static final char MAP_INFO = 0x0301;
|
||||||
|
/**
|
||||||
|
* Hit points
|
||||||
|
*/
|
||||||
|
private int hp;
|
||||||
|
/**
|
||||||
|
* Maximum hit points
|
||||||
|
*/
|
||||||
|
private static final int maxHp = GameServer.INSTANCE.getConfig().getInt("electric_box_hp");
|
||||||
|
/**
|
||||||
|
* Number of hit points dealt to nearby objects each tick
|
||||||
|
*/
|
||||||
|
private static final int damageDealt = GameServer.INSTANCE.getConfig().getInt("electric_box_damage");
|
||||||
|
/**
|
||||||
|
* Number of energy points given to nearby objects each tick
|
||||||
|
*/
|
||||||
|
private static final int energyGiven = GameServer.INSTANCE.getConfig().getInt("electric_box_energy_given");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of nearby objects. Is updated every tick
|
||||||
|
*/
|
||||||
|
private ArrayList<Attackable> nearObjects = new ArrayList<>();
|
||||||
|
|
||||||
|
public ElectricBox() {
|
||||||
|
hp = maxHp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElectricBox(Document document) {
|
||||||
|
super(document);
|
||||||
|
hp = document.getInteger("hp");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently has no effect
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setHealRate(int hp) {
|
||||||
|
//no op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHp() {
|
||||||
|
return hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHp(int hp) {
|
||||||
|
this.hp = hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxHp() {
|
||||||
|
return hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently has no effect
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setMaxHp(int hp) {
|
||||||
|
//No op
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currently has no effect
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void heal(int amount) {
|
||||||
|
//No op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void damage(int amount) {
|
||||||
|
hp -= amount;
|
||||||
|
|
||||||
|
//YOU ARE DEAD
|
||||||
|
if (hp <= 0) {
|
||||||
|
setDead(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getMapInfo() {
|
||||||
|
return MAP_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the current list nearby objects
|
||||||
|
* <br>An object is considered 'nearby' if its Manhattan distance is {@literal <= @} 1 and is Attackable
|
||||||
|
*/
|
||||||
|
private void updateNearObjects() {
|
||||||
|
|
||||||
|
nearObjects.clear();
|
||||||
|
|
||||||
|
for (GameObject object : getWorld().getGameObjects()) {
|
||||||
|
if (object != this && object instanceof Attackable && Util.manhattanDist(object.getX(), object.getY(),
|
||||||
|
getX(), getY()) <= 1) {
|
||||||
|
nearObjects.add((Attackable) object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called every tick
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
|
||||||
|
updateNearObjects();
|
||||||
|
|
||||||
|
for (Attackable obj : nearObjects) {
|
||||||
|
obj.damage(damageDealt);
|
||||||
|
|
||||||
|
if (obj instanceof Rechargeable) {
|
||||||
|
((Rechargeable) obj).storeEnergy(energyGiven);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject jsonSerialise() {
|
||||||
|
JSONObject json = super.jsonSerialise();
|
||||||
|
|
||||||
|
json.put("hp", hp);
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document dbObject = super.mongoSerialise();
|
||||||
|
|
||||||
|
dbObject.put("hp", getHp());
|
||||||
|
|
||||||
|
return dbObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onDeadCallback() {
|
||||||
|
getWorld().decUpdatable();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.game.objects.Action;
|
||||||
|
|
||||||
|
public class ExecuteCpuTask extends NPCTask {
|
||||||
|
|
||||||
|
private static final int MAX_EXEC_TIME = GameServer.INSTANCE.getConfig().getInt("npc_exec_time");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkCompleted() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(NonPlayerCharacter npc) {
|
||||||
|
|
||||||
|
HackedNPC hNpc = (HackedNPC) npc;
|
||||||
|
|
||||||
|
//Execute code
|
||||||
|
int timeout = Math.min(hNpc.getEnergy(), MAX_EXEC_TIME);
|
||||||
|
hNpc.getCpu().reset();
|
||||||
|
int cost = hNpc.getCpu().execute(timeout);
|
||||||
|
hNpc.spendEnergy(cost);
|
||||||
|
|
||||||
|
if (hNpc.getCurrentAction() == Action.WALKING) {
|
||||||
|
if (hNpc.spendEnergy(100)) {
|
||||||
|
if (hNpc.incrementLocation()) {
|
||||||
|
//Couldn't walk
|
||||||
|
hNpc.setCurrentAction(Action.IDLE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hNpc.setCurrentAction(Action.IDLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,210 +1,157 @@
|
|||||||
package net.simon987.npcplugin;
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBList;
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.game.GameObject;
|
import net.simon987.server.game.objects.MessageReceiver;
|
||||||
import net.simon987.server.game.Updatable;
|
import net.simon987.server.game.objects.Structure;
|
||||||
import org.json.simple.JSONArray;
|
import net.simon987.server.game.objects.Updatable;
|
||||||
import org.json.simple.JSONObject;
|
import org.bson.Document;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.ArrayList;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class Factory extends GameObject implements Updatable {
|
/**
|
||||||
|
* Game objects that regularly creates NonPlayerCharacters
|
||||||
|
*/
|
||||||
|
public class Factory extends Structure implements Updatable, MessageReceiver {
|
||||||
|
|
||||||
private static final int MAP_INFO = 0x0200;
|
private static final int MAP_INFO = 0x0401;
|
||||||
static final int ID = 3;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of NonPlayerCharacters assigned to this Factory
|
||||||
|
*/
|
||||||
private static final int MAX_NPC_COUNT = GameServer.INSTANCE.getConfig().getInt("factory_max_npc_count");
|
private static final int MAX_NPC_COUNT = GameServer.INSTANCE.getConfig().getInt("factory_max_npc_count");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of ticks to wait after creating a NonPlayerCharacter
|
||||||
|
*/
|
||||||
private static final int NPC_CREATION_COOLDOWN = NonPlayerCharacter.LIFETIME / MAX_NPC_COUNT;
|
private static final int NPC_CREATION_COOLDOWN = NonPlayerCharacter.LIFETIME / MAX_NPC_COUNT;
|
||||||
|
|
||||||
private ArrayList<NonPlayerCharacter> npcs = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of ticks to wait until the Factory can spawn a new NPC
|
* Number of ticks to wait until the Factory can spawn a new NPC
|
||||||
*/
|
*/
|
||||||
private int cooldown = 0;
|
private int cooldown = 0;
|
||||||
|
|
||||||
/**
|
private boolean locked = true;
|
||||||
* Temporary NPC objectId array. The Factory links the NPCs to itself when initialised,
|
|
||||||
* at the first call of update().
|
|
||||||
*/
|
|
||||||
private Object[] tmpNpcArray = new Object[0];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory are uninitialised until the first update() call
|
* If non-null, the next spawned NPC will be a HackedNPC and the program will be
|
||||||
|
* injected in its memory
|
||||||
*/
|
*/
|
||||||
private boolean initialised = false;
|
private char[] program;
|
||||||
|
private int programIndex = 0;
|
||||||
|
|
||||||
|
private static final int PROGRAM_SIZE = GameServer.INSTANCE.getConfig().getInt("factory_program_size");
|
||||||
|
|
||||||
|
public Factory() {
|
||||||
|
super(2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Factory(Document document) {
|
||||||
|
super(document, 2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char getMapInfo() {
|
public char getMapInfo() {
|
||||||
return MAP_INFO;
|
return MAP_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called every tick
|
||||||
|
* <br>The fist time this is called, NPCs retrieved from the database are linked to the Factory
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
|
|
||||||
if (!initialised) {
|
Settlement settlement = NpcPlugin.settlementMap.get(getWorld().getId());
|
||||||
|
|
||||||
initialised = true;
|
if (settlement == null) {
|
||||||
|
//Only happens when server is killed during save function
|
||||||
|
getWorld().decUpdatable();
|
||||||
|
setDead(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (Object id : tmpNpcArray) {
|
if (cooldown == 0) {
|
||||||
|
if (settlement.getNpcs().size() < MAX_NPC_COUNT) {
|
||||||
|
Point p = getAdjacentTile();
|
||||||
|
|
||||||
NonPlayerCharacter npc = (NonPlayerCharacter) GameServer.INSTANCE.getGameUniverse().getObject((int) (long) id);
|
if (p != null) {
|
||||||
|
NonPlayerCharacter npc = spawnNPC(p);
|
||||||
|
settlement.addNpc(npc);
|
||||||
|
|
||||||
if (npc != null) {
|
getWorld().addObject(npc);
|
||||||
npc.setFactory(this);
|
getWorld().incUpdatable();
|
||||||
npcs.add(npc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cooldown += NPC_CREATION_COOLDOWN;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
cooldown--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cooldown == 0) {
|
private NonPlayerCharacter spawnNPC(Point p) {
|
||||||
if (npcs.size() < MAX_NPC_COUNT) {
|
|
||||||
Point p = getAdjacentTile();
|
|
||||||
|
|
||||||
if (p != null) {
|
NonPlayerCharacter npc;
|
||||||
NonPlayerCharacter npc = new HarvesterNPC();
|
|
||||||
npc.setWorld(getWorld());
|
|
||||||
npc.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
|
||||||
npc.setX(p.x);
|
|
||||||
npc.setY(p.y);
|
|
||||||
getWorld().addObject(npc);
|
|
||||||
getWorld().incUpdatable();
|
|
||||||
npc.setFactory(this);
|
|
||||||
|
|
||||||
npcs.add(npc);
|
if (programIndex == 0) {
|
||||||
}
|
npc = spawnRandomNpc(p);
|
||||||
}
|
} else {
|
||||||
|
npc = spawnHackedNpc(p);
|
||||||
|
}
|
||||||
|
|
||||||
cooldown += NPC_CREATION_COOLDOWN;
|
return npc;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
private NonPlayerCharacter spawnRandomNpc(Point p) {
|
||||||
cooldown--;
|
NonPlayerCharacter npc;
|
||||||
|
npc = new HarvesterNPC();
|
||||||
|
npc.setWorld(getWorld());
|
||||||
|
npc.setObjectId(new ObjectId());
|
||||||
|
npc.setX(p.x);
|
||||||
|
npc.setY(p.y);
|
||||||
|
return npc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NonPlayerCharacter spawnHackedNpc(Point p) {
|
||||||
|
NonPlayerCharacter npc;
|
||||||
|
npc = new HackedNPC(program);
|
||||||
|
npc.setWorld(getWorld());
|
||||||
|
npc.setObjectId(new ObjectId());
|
||||||
|
npc.setX(p.x);
|
||||||
|
npc.setY(p.y);
|
||||||
|
|
||||||
|
this.locked = true;
|
||||||
|
this.programIndex = 0;
|
||||||
|
|
||||||
|
return npc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean sendMessage(char[] message) {
|
||||||
|
|
||||||
|
if (locked) {
|
||||||
|
Settlement settlement = NpcPlugin.settlementMap.get(getWorld().getId());
|
||||||
|
|
||||||
|
if (Arrays.equals(settlement.getPassword(), message)) {
|
||||||
|
this.locked = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
} else if (programIndex <= PROGRAM_SIZE) {
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (programIndex == 0) {
|
||||||
public boolean isAt(int x, int y) {
|
program = new char[PROGRAM_SIZE];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
System.arraycopy(message, 0, program, programIndex, message.length);
|
||||||
* Object is 2x2 tiles, the (x,y) coordinates of the object being
|
programIndex += message.length;
|
||||||
* at top-left.
|
|
||||||
* # .
|
|
||||||
* . .
|
|
||||||
*/
|
|
||||||
return (x == getX() + 1 || x == getX()) && (y == getY() + 1 || y == getY());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
return true;
|
||||||
public JSONObject serialise() {
|
|
||||||
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
|
|
||||||
json.put("i", getObjectId());
|
|
||||||
json.put("x", getX());
|
|
||||||
json.put("y", getY());
|
|
||||||
json.put("t", ID);
|
|
||||||
|
|
||||||
JSONArray tmpNpcArray = new JSONArray();
|
|
||||||
|
|
||||||
for (NonPlayerCharacter npc : npcs) {
|
|
||||||
tmpNpcArray.add(npc.getObjectId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
json.put("n", tmpNpcArray);
|
return true;
|
||||||
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BasicDBObject mongoSerialise() {
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
|
||||||
|
|
||||||
dbObject.put("i", getObjectId());
|
|
||||||
dbObject.put("x", getX());
|
|
||||||
dbObject.put("y", getY());
|
|
||||||
dbObject.put("t", ID);
|
|
||||||
|
|
||||||
BasicDBList tmpNpcArray = new BasicDBList();
|
|
||||||
|
|
||||||
for (NonPlayerCharacter npc : npcs) {
|
|
||||||
tmpNpcArray.add(npc.getObjectId());
|
|
||||||
}
|
|
||||||
|
|
||||||
dbObject.put("n", tmpNpcArray);
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Factory deserialise(DBObject obj) {
|
|
||||||
|
|
||||||
Factory factory = new Factory();
|
|
||||||
factory.setObjectId((long) obj.get("i"));
|
|
||||||
factory.setX((int) obj.get("x"));
|
|
||||||
factory.setY((int) obj.get("y"));
|
|
||||||
|
|
||||||
factory.tmpNpcArray = ((BasicDBList) obj.get("n")).toArray();
|
|
||||||
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the first non-blocked tile that is directly adjacent to the factory, starting from the north-east corner
|
|
||||||
* going clockwise.
|
|
||||||
*
|
|
||||||
* @return The coordinates of the first non-blocked tile, null otherwise.
|
|
||||||
*/
|
|
||||||
public Point getAdjacentTile() {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (2,0)
|
|
||||||
* (2,1)
|
|
||||||
* (1,2)
|
|
||||||
* (0,2)
|
|
||||||
* (-1,1)
|
|
||||||
* (-1,0)
|
|
||||||
* (0,-1)
|
|
||||||
* (1,-1)
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!getWorld().isTileBlocked(getX() + 2, getY())) {
|
|
||||||
return new Point(getX() + 2, getY());
|
|
||||||
|
|
||||||
} else if (!getWorld().isTileBlocked(getX() + 2, getY() + 1)) {
|
|
||||||
return new Point(getX() + 2, getY() + 1);
|
|
||||||
|
|
||||||
} else if (!getWorld().isTileBlocked(getX() + 1, getY() + 2)) {
|
|
||||||
return new Point(getX() + 1, getY() + 2);
|
|
||||||
|
|
||||||
} else if (!getWorld().isTileBlocked(getX(), getY() + 2)) {
|
|
||||||
return new Point(getX(), getY() + 2);
|
|
||||||
|
|
||||||
} else if (!getWorld().isTileBlocked(getX() + -1, getY() + 1)) {
|
|
||||||
return new Point(getX() + -1, getY() + 1);
|
|
||||||
|
|
||||||
} else if (!getWorld().isTileBlocked(getX() + -1, getY())) {
|
|
||||||
return new Point(getX() + -1, getY());
|
|
||||||
|
|
||||||
} else if (!getWorld().isTileBlocked(getX(), getY() + -1)) {
|
|
||||||
return new Point(getX(), getY() + -1);
|
|
||||||
|
|
||||||
} else if (!getWorld().isTileBlocked(getX() + 1, getY() + -1)) {
|
|
||||||
return new Point(getX() + 1, getY() + -1);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<NonPlayerCharacter> getNpcs() {
|
|
||||||
return npcs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
339
Plugin NPC/src/main/java/net/simon987/npcplugin/HackedNPC.java
Normal file
339
Plugin NPC/src/main/java/net/simon987/npcplugin/HackedNPC.java
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.assembly.*;
|
||||||
|
import net.simon987.server.event.ObjectDeathEvent;
|
||||||
|
import net.simon987.server.game.item.Item;
|
||||||
|
import net.simon987.server.game.item.ItemVoid;
|
||||||
|
import net.simon987.server.game.objects.Action;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import net.simon987.server.game.objects.Direction;
|
||||||
|
import net.simon987.server.logging.LogManager;
|
||||||
|
import net.simon987.server.user.User;
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class HackedNPC extends NonPlayerCharacter implements ControllableUnit {
|
||||||
|
|
||||||
|
private static final int MEM_SIZE = GameServer.INSTANCE.getConfig().getInt("hacked_npc_mem_size");
|
||||||
|
private static final boolean DIE_ON_NO_ENERGY = GameServer.INSTANCE.getConfig().getInt("hacked_npc_die_on_no_energy") != 0;
|
||||||
|
|
||||||
|
private CPU cpu;
|
||||||
|
/**
|
||||||
|
* List of attached hardware, 'modules'
|
||||||
|
*/
|
||||||
|
private Map<Integer, HardwareModule> hardwareAddresses = new HashMap<>();
|
||||||
|
private Map<Class<? extends HardwareModule>, Integer> hardwareModules = new HashMap<>();
|
||||||
|
|
||||||
|
private Action currentAction = Action.IDLE;
|
||||||
|
private Action lastAction = Action.IDLE;
|
||||||
|
private ArrayList<char[]> consoleMessagesBuffer = new ArrayList<>(30); //todo load from conf
|
||||||
|
private ArrayList<char[]> lastConsoleMessagesBuffer = new ArrayList<>(30);
|
||||||
|
|
||||||
|
HackedNPC(char[] program) {
|
||||||
|
|
||||||
|
cpu = new CPU();
|
||||||
|
|
||||||
|
cpu.setMemory(new Memory(MEM_SIZE));
|
||||||
|
cpu.setHardwareHost(this);
|
||||||
|
cpu.getMemory().write(cpu.getCodeSectionOffset(), program, 0, program.length);
|
||||||
|
|
||||||
|
for (Object serialisedHw : (List) NpcPlugin.DEFAULT_HACKED_NPC.get("hardware")) {
|
||||||
|
HardwareModule hardware = GameServer.INSTANCE.getRegistry().deserializeHardware((Document) serialisedHw, this);
|
||||||
|
hardware.setCpu(cpu);
|
||||||
|
attachHardware(hardware, ((Document) serialisedHw).getInteger("address"));
|
||||||
|
}
|
||||||
|
|
||||||
|
setTask(new ExecuteCpuTask());
|
||||||
|
}
|
||||||
|
|
||||||
|
public HackedNPC(Document document) {
|
||||||
|
super(document);
|
||||||
|
|
||||||
|
setHp(document.getInteger("hp"));
|
||||||
|
setDirection(Direction.getDirection(document.getInteger("direction")));
|
||||||
|
|
||||||
|
cpu = new CPU();
|
||||||
|
cpu.setHardwareHost(this);
|
||||||
|
cpu.setMemory(new Memory((Document) document.get("memory")));
|
||||||
|
cpu.setRegisterSet(RegisterSet.deserialize((Document) document.get("registerSet")));
|
||||||
|
|
||||||
|
ArrayList hardwareList = (ArrayList) document.get("hardware");
|
||||||
|
|
||||||
|
for (Object serialisedHw : hardwareList) {
|
||||||
|
HardwareModule hardware = GameServer.INSTANCE.getRegistry().deserializeHardware((Document) serialisedHw, this);
|
||||||
|
hardware.setCpu(cpu);
|
||||||
|
attachHardware(hardware, ((Document) serialisedHw).getInteger("address"));
|
||||||
|
}
|
||||||
|
|
||||||
|
setTask(new ExecuteCpuTask());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
super.update();
|
||||||
|
|
||||||
|
lastAction = currentAction;
|
||||||
|
currentAction = Action.IDLE;
|
||||||
|
|
||||||
|
lastConsoleMessagesBuffer = new ArrayList<>(consoleMessagesBuffer);
|
||||||
|
consoleMessagesBuffer.clear();
|
||||||
|
|
||||||
|
for (HardwareModule module : hardwareAddresses.values()) {
|
||||||
|
module.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Self-destroy when age limit is reached
|
||||||
|
if (getAge() >= NonPlayerCharacter.LIFETIME) {
|
||||||
|
setDead(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Don't bother calling checkCompleted()
|
||||||
|
getTask().tick(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setKeyboardBuffer(ArrayList<Integer> kbBuffer) {
|
||||||
|
LogManager.LOGGER.warning("Something went wrong here: Hacked NPC has no keyboard module" +
|
||||||
|
"@HackedNPC::setKeyBoardBuffer()");
|
||||||
|
Thread.dumpStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParent(User user) {
|
||||||
|
LogManager.LOGGER.warning("Something went wrong here: Hacked NPC has no parent" +
|
||||||
|
"@HackedNPC::setParent()");
|
||||||
|
Thread.dumpStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getParent() {
|
||||||
|
LogManager.LOGGER.warning("Something went wrong here: Hacked NPC has no parent" +
|
||||||
|
"@HackedNPC::getParent()");
|
||||||
|
Thread.dumpStack();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<Integer> getKeyboardBuffer() {
|
||||||
|
LogManager.LOGGER.warning("Something went wrong here: Hacked NPC has no keyboard module" +
|
||||||
|
"@HackedNPC::getKeyBoardBuffer()");
|
||||||
|
Thread.dumpStack();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Memory getFloppyData() {
|
||||||
|
LogManager.LOGGER.warning("Something went wrong here: Hacked NPC has floppy data." +
|
||||||
|
"@HackedNPC::getFloppyData()");
|
||||||
|
Thread.dumpStack();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAction(Action action) {
|
||||||
|
currentAction = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<char[]> getConsoleMessagesBuffer() {
|
||||||
|
return lastConsoleMessagesBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getConsoleMode() {
|
||||||
|
LogManager.LOGGER.warning("Something went wrong here: Hacked NPC has no console UI." +
|
||||||
|
"@HackedNPC::getConsoleMode()");
|
||||||
|
Thread.dumpStack();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CPU getCpu() {
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void giveItem(Item item) {
|
||||||
|
//Overwrite item at current position
|
||||||
|
((NpcInventory) getHardware(NpcInventory.class)).putItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attachHardware(HardwareModule hardware, int address) {
|
||||||
|
hardwareAddresses.put(address, hardware);
|
||||||
|
hardwareModules.put(hardware.getClass(), address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detachHardware(int address) {
|
||||||
|
hardwareAddresses.remove(address);
|
||||||
|
|
||||||
|
Class<? extends HardwareModule> toRemove = null;
|
||||||
|
for (Class<? extends HardwareModule> clazz : hardwareModules.keySet()) {
|
||||||
|
if (hardwareModules.get(clazz) == address) {
|
||||||
|
toRemove = clazz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hardwareModules.remove(toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hardwareInterrupt(int address, Status status) {
|
||||||
|
HardwareModule hardware = hardwareAddresses.get(address);
|
||||||
|
|
||||||
|
if (hardware != null) {
|
||||||
|
hardware.handleInterrupt(status);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hardwareQuery(int address) {
|
||||||
|
HardwareModule hardware = hardwareAddresses.get(address);
|
||||||
|
|
||||||
|
if (hardware != null) {
|
||||||
|
return hardware.getId();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEnergy() {
|
||||||
|
NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class);
|
||||||
|
return battery.getEnergy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnergy(int energy) {
|
||||||
|
NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class);
|
||||||
|
battery.setEnergy(energy);
|
||||||
|
|
||||||
|
if (energy == 0 && DIE_ON_NO_ENERGY) {
|
||||||
|
setDead(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean spendEnergy(int amount) {
|
||||||
|
|
||||||
|
NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class);
|
||||||
|
|
||||||
|
if (battery.getEnergy() - amount < 0) {
|
||||||
|
if (DIE_ON_NO_ENERGY) {
|
||||||
|
setDead(true);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
battery.setEnergy(battery.getEnergy() - amount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document dbObject = super.mongoSerialise();
|
||||||
|
|
||||||
|
dbObject.put("direction", getDirection().ordinal());
|
||||||
|
dbObject.put("hp", getHp());
|
||||||
|
dbObject.put("action", lastAction.ordinal());
|
||||||
|
|
||||||
|
List<Document> hardwareList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Integer address : hardwareAddresses.keySet()) {
|
||||||
|
|
||||||
|
HardwareModule hardware = hardwareAddresses.get(address);
|
||||||
|
|
||||||
|
Document serialisedHw = hardware.mongoSerialise();
|
||||||
|
serialisedHw.put("address", address);
|
||||||
|
hardwareList.add(serialisedHw);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbObject.put("hardware", hardwareList);
|
||||||
|
|
||||||
|
dbObject.put("memory", cpu.getMemory().mongoSerialise());
|
||||||
|
|
||||||
|
dbObject.put("registerSet", cpu.getRegisterSet().mongoSerialise());
|
||||||
|
return dbObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void storeEnergy(int amount) {
|
||||||
|
|
||||||
|
NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class);
|
||||||
|
battery.setEnergy(Math.min(battery.getEnergy() + amount, battery.getMaxEnergy()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private HardwareModule getHardware(Class<? extends HardwareModule> clazz) {
|
||||||
|
return hardwareAddresses.get(hardwareModules.get(clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxEnergy(int maxEnergy) {
|
||||||
|
NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class);
|
||||||
|
battery.setMaxEnergy(maxEnergy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxEnergy() {
|
||||||
|
NpcBattery battery = (NpcBattery) getHardware(NpcBattery.class);
|
||||||
|
return battery.getMaxEnergy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean sendMessage(char[] message) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCurrentAction(Action action) {
|
||||||
|
currentAction = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action getCurrentAction() {
|
||||||
|
return currentAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject jsonSerialise() {
|
||||||
|
JSONObject json = super.jsonSerialise();
|
||||||
|
|
||||||
|
for (HardwareModule module : hardwareAddresses.values()) {
|
||||||
|
JSONObject hwJson = module.jsonSerialise();
|
||||||
|
if (hwJson != null) {
|
||||||
|
json.put(module.getClass().getName(), hwJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json.put("direction", getDirection().ordinal());
|
||||||
|
NpcInventory inv = (NpcInventory) getHardware(NpcInventory.class);
|
||||||
|
Item item = inv.getItem();
|
||||||
|
json.put("heldItem", item == null ? new ItemVoid().getId() : item.getId());
|
||||||
|
json.put("hp", getHp());
|
||||||
|
json.put("action", lastAction.ordinal());
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onDeadCallback() {
|
||||||
|
|
||||||
|
getWorld().decUpdatable();
|
||||||
|
|
||||||
|
if (getSettlement() != null && getSettlement().getNpcs() != null) {
|
||||||
|
getSettlement().getNpcs().remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameServer.INSTANCE.getEventDispatcher().dispatch(new ObjectDeathEvent(this));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject debugJsonSerialise() {
|
||||||
|
return jsonSerialise();
|
||||||
|
}
|
||||||
|
}
|
@ -2,27 +2,39 @@ package net.simon987.npcplugin;
|
|||||||
|
|
||||||
|
|
||||||
import net.simon987.server.assembly.Util;
|
import net.simon987.server.assembly.Util;
|
||||||
import net.simon987.server.game.Direction;
|
import net.simon987.server.game.objects.Direction;
|
||||||
import net.simon987.server.game.GameObject;
|
import net.simon987.server.game.objects.GameObject;
|
||||||
import net.simon987.server.game.InventoryHolder;
|
import net.simon987.server.game.objects.InventoryHolder;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find Biomass, move towards it, collect it, repeat
|
||||||
|
*/
|
||||||
public class HarvestTask extends NPCTask {
|
public class HarvestTask extends NPCTask {
|
||||||
|
|
||||||
private Random random;
|
private Random random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of ticks to wait before continuing
|
||||||
|
*/
|
||||||
private int pause;
|
private int pause;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Direction of the next world to visit (randomly chosen)
|
||||||
|
*/
|
||||||
|
private Direction nextWorldDirection = null;
|
||||||
|
|
||||||
public HarvestTask() {
|
public HarvestTask() {
|
||||||
random = new Random();
|
random = new Random();
|
||||||
pause = 0;
|
pause = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Direction nextWorldDirection = null;
|
/**
|
||||||
|
* This task never finishes
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean checkCompleted() {
|
public boolean checkCompleted() {
|
||||||
return false;
|
return false;
|
||||||
@ -33,9 +45,7 @@ public class HarvestTask extends NPCTask {
|
|||||||
|
|
||||||
if (pause == 0) {
|
if (pause == 0) {
|
||||||
//Get biomass
|
//Get biomass
|
||||||
/* todo replace by some sort of .collect call with object
|
ArrayList<GameObject> biomass = npc.getWorld().findGameObjects("net.simon987.biomassplugin.BiomassBlob");
|
||||||
id (See https://github.com/simon987/Much-Assembly-Required/pull/66)*/
|
|
||||||
ArrayList<GameObject> biomass = npc.getWorld().findObjects(0x4000);
|
|
||||||
|
|
||||||
//Get closest one
|
//Get closest one
|
||||||
int minDist = Integer.MAX_VALUE;
|
int minDist = Integer.MAX_VALUE;
|
||||||
@ -93,8 +103,5 @@ public class HarvestTask extends NPCTask {
|
|||||||
} else {
|
} else {
|
||||||
pause--;
|
pause--;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,17 @@
|
|||||||
package net.simon987.npcplugin;
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.event.ObjectDeathEvent;
|
import net.simon987.server.event.ObjectDeathEvent;
|
||||||
import net.simon987.server.game.Direction;
|
import net.simon987.server.game.objects.Direction;
|
||||||
|
import org.bson.Document;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
|
||||||
public class HarvesterNPC extends NonPlayerCharacter {
|
public class HarvesterNPC extends NonPlayerCharacter {
|
||||||
|
|
||||||
public static final int ID = 10;
|
|
||||||
|
|
||||||
public static final int MAX_HEALTH = GameServer.INSTANCE.getConfig().getInt("harvester_hp_max");
|
public static final int MAX_HEALTH = GameServer.INSTANCE.getConfig().getInt("harvester_hp_max");
|
||||||
public static final int HEAL_RATE = GameServer.INSTANCE.getConfig().getInt("harvester_regen");
|
public static final int HEAL_RATE = GameServer.INSTANCE.getConfig().getInt("harvester_regen");
|
||||||
|
|
||||||
|
|
||||||
public HarvesterNPC() {
|
public HarvesterNPC() {
|
||||||
setTask(new HarvestTask());
|
setTask(new HarvestTask());
|
||||||
|
|
||||||
@ -24,12 +20,19 @@ public class HarvesterNPC extends NonPlayerCharacter {
|
|||||||
setHealRate(HEAL_RATE);
|
setHealRate(HEAL_RATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HarvesterNPC(Document document) {
|
||||||
|
super(document);
|
||||||
|
|
||||||
|
setTask(new HarvestTask());
|
||||||
|
|
||||||
|
setDirection(Direction.getDirection(document.getInteger("direction")));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
|
|
||||||
super.update();
|
super.update();
|
||||||
|
|
||||||
if (getFactory() != null) {
|
if (getSettlement() != null) {
|
||||||
if (getTask().checkCompleted()) {
|
if (getTask().checkCompleted()) {
|
||||||
|
|
||||||
setTask(new HarvestTask());
|
setTask(new HarvestTask());
|
||||||
@ -46,60 +49,47 @@ public class HarvesterNPC extends NonPlayerCharacter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeadCallback() {
|
public boolean onDeadCallback() {
|
||||||
|
|
||||||
if (getFactory() != null && getFactory().getNpcs() != null) {
|
getWorld().decUpdatable();
|
||||||
getFactory().getNpcs().remove(this);
|
|
||||||
|
if (getSettlement() != null && getSettlement().getNpcs() != null) {
|
||||||
|
getSettlement().getNpcs().remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameServer.INSTANCE.getEventDispatcher().dispatch(
|
GameServer.INSTANCE.getEventDispatcher().dispatch(new ObjectDeathEvent(this));
|
||||||
new ObjectDeathEvent(this, ID));
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject serialise() {
|
public JSONObject jsonSerialise() {
|
||||||
JSONObject json = super.serialise();
|
JSONObject json = super.jsonSerialise();
|
||||||
|
|
||||||
json.put("i", getObjectId());
|
|
||||||
json.put("x", getX());
|
|
||||||
json.put("y", getY());
|
|
||||||
json.put("direction", getDirection().ordinal());
|
json.put("direction", getDirection().ordinal());
|
||||||
json.put("hp", getHp());
|
json.put("hp", getHp());
|
||||||
json.put("energy", energy);
|
|
||||||
json.put("action", getAction().ordinal());
|
json.put("action", getAction().ordinal());
|
||||||
json.put("t", ID);
|
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public JSONObject debugJsonSerialise() {
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
JSONObject json = jsonSerialise();
|
||||||
|
|
||||||
|
json.put("taskCompleted", getTask().checkCompleted());
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document dbObject = super.mongoSerialise();
|
||||||
|
|
||||||
dbObject.put("i", getObjectId());
|
|
||||||
dbObject.put("x", getX());
|
|
||||||
dbObject.put("y", getY());
|
|
||||||
dbObject.put("direction", getDirection().ordinal());
|
dbObject.put("direction", getDirection().ordinal());
|
||||||
dbObject.put("hp", getHp());
|
dbObject.put("hp", getHp());
|
||||||
// dbObject.put("energy", energy);
|
|
||||||
dbObject.put("action", getAction().ordinal());
|
dbObject.put("action", getAction().ordinal());
|
||||||
dbObject.put("t", ID);
|
|
||||||
|
|
||||||
return dbObject;
|
return dbObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HarvesterNPC deserialize(DBObject obj) {
|
|
||||||
|
|
||||||
HarvesterNPC npc = new HarvesterNPC();
|
|
||||||
npc.setObjectId((long) obj.get("i"));
|
|
||||||
npc.setX((int) obj.get("x"));
|
|
||||||
npc.setY((int) obj.get("y"));
|
|
||||||
npc.setHp((int) obj.get("hp"));
|
|
||||||
npc.setDirection(Direction.getDirection((int) obj.get("direction")));
|
|
||||||
// npc.energy = (int) obj.get("energy");
|
|
||||||
// npc.maxEnergy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy");
|
|
||||||
|
|
||||||
return npc;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,46 +2,46 @@ package net.simon987.npcplugin;
|
|||||||
|
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.assembly.Util;
|
import net.simon987.server.assembly.Util;
|
||||||
import net.simon987.server.game.*;
|
import net.simon987.server.game.objects.*;
|
||||||
import net.simon987.server.game.pathfinding.Node;
|
import net.simon987.server.game.pathfinding.Node;
|
||||||
import net.simon987.server.game.pathfinding.Pathfinder;
|
import net.simon987.server.game.pathfinding.Pathfinder;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Game object that actively interacts with the game world by doing tasks
|
||||||
|
*/
|
||||||
public abstract class NonPlayerCharacter extends GameObject implements Updatable, Attackable {
|
public abstract class NonPlayerCharacter extends GameObject implements Updatable, Attackable {
|
||||||
|
|
||||||
private static final int MAP_INFO = 0x0040;
|
private static final char MAP_INFO = 0x0501;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum distance to travel from its factory, in Worlds
|
||||||
|
*/
|
||||||
private static final int MAX_FACTORY_DISTANCE = GameServer.INSTANCE.getConfig().getInt("npc_max_factory_distance");
|
private static final int MAX_FACTORY_DISTANCE = GameServer.INSTANCE.getConfig().getInt("npc_max_factory_distance");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of ticks to live
|
||||||
|
*/
|
||||||
public static final int LIFETIME = GameServer.INSTANCE.getConfig().getInt("npc_lifetime");
|
public static final int LIFETIME = GameServer.INSTANCE.getConfig().getInt("npc_lifetime");
|
||||||
|
|
||||||
// Set these just in case they aren't overridden in the subclass
|
// Set these just in case they aren't overridden in the subclass
|
||||||
public static final int HP_MAX_DEFAULT = 100;
|
public static final int HP_MAX_DEFAULT = 100;
|
||||||
public static final int HP_REGEN_RATE_DEFAULT = 0;
|
public static final int HP_REGEN_RATE_DEFAULT = 0;
|
||||||
|
|
||||||
//Unused
|
|
||||||
int energy;
|
|
||||||
int maxEnergy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current task
|
* Current task
|
||||||
*/
|
*/
|
||||||
private NPCTask task;
|
private NPCTask task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action at the end of the last tick
|
||||||
|
*/
|
||||||
private Action lastAction = Action.IDLE;
|
private Action lastAction = Action.IDLE;
|
||||||
|
|
||||||
/**
|
private Settlement settlement;
|
||||||
* Factory that created this NPC
|
|
||||||
*/
|
|
||||||
private Factory factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If set to true, the NPC will be destroyed next tick if it is
|
|
||||||
* not linked to a Factory
|
|
||||||
*/
|
|
||||||
private boolean selfDestroyNextTick = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Age of the npc, in ticks
|
* Age of the npc, in ticks
|
||||||
@ -63,6 +63,17 @@ public abstract class NonPlayerCharacter extends GameObject implements Updatable
|
|||||||
*/
|
*/
|
||||||
private int maxHp = HP_MAX_DEFAULT;
|
private int maxHp = HP_MAX_DEFAULT;
|
||||||
|
|
||||||
|
public NonPlayerCharacter() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public NonPlayerCharacter(Document document) {
|
||||||
|
super(document);
|
||||||
|
|
||||||
|
hp = document.getInteger("hp");
|
||||||
|
setDirection(Direction.getDirection(document.getInteger("direction")));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char getMapInfo() {
|
public char getMapInfo() {
|
||||||
return MAP_INFO;
|
return MAP_INFO;
|
||||||
@ -73,13 +84,9 @@ public abstract class NonPlayerCharacter extends GameObject implements Updatable
|
|||||||
|
|
||||||
age++;
|
age++;
|
||||||
|
|
||||||
//Destroy NPCs that are not linked with a Factory
|
//Destroy NPCs that are not linked with a Settlement
|
||||||
if (factory == null) {
|
if (settlement == null) {
|
||||||
if (selfDestroyNextTick) {
|
setDead(true);
|
||||||
setDead(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
selfDestroyNextTick = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Heal the NPC
|
//Heal the NPC
|
||||||
@ -127,7 +134,7 @@ public abstract class NonPlayerCharacter extends GameObject implements Updatable
|
|||||||
|
|
||||||
if (direction == Direction.NORTH) {
|
if (direction == Direction.NORTH) {
|
||||||
|
|
||||||
if (Util.manhattanDist(factory.getWorld().getX(), factory.getWorld().getY(),
|
if (Util.manhattanDist(settlement.getWorld().getX(), settlement.getWorld().getY(),
|
||||||
getWorld().getX(), getWorld().getY() - 1) <= MAX_FACTORY_DISTANCE) {
|
getWorld().getX(), getWorld().getY() - 1) <= MAX_FACTORY_DISTANCE) {
|
||||||
if (!moveTo(8, 0, 0)) {
|
if (!moveTo(8, 0, 0)) {
|
||||||
setDirection(Direction.NORTH);
|
setDirection(Direction.NORTH);
|
||||||
@ -139,7 +146,7 @@ public abstract class NonPlayerCharacter extends GameObject implements Updatable
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (direction == Direction.EAST) {
|
} else if (direction == Direction.EAST) {
|
||||||
if (Util.manhattanDist(factory.getWorld().getX(), factory.getWorld().getY(),
|
if (Util.manhattanDist(settlement.getWorld().getX(), settlement.getWorld().getY(),
|
||||||
getWorld().getX() + 1, getWorld().getY()) <= MAX_FACTORY_DISTANCE) {
|
getWorld().getX() + 1, getWorld().getY()) <= MAX_FACTORY_DISTANCE) {
|
||||||
if (!moveTo(15, 7, 0)) {
|
if (!moveTo(15, 7, 0)) {
|
||||||
setDirection(Direction.EAST);
|
setDirection(Direction.EAST);
|
||||||
@ -150,7 +157,7 @@ public abstract class NonPlayerCharacter extends GameObject implements Updatable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (direction == Direction.SOUTH) {
|
} else if (direction == Direction.SOUTH) {
|
||||||
if (Util.manhattanDist(factory.getWorld().getX(), factory.getWorld().getY(),
|
if (Util.manhattanDist(settlement.getWorld().getX(), settlement.getWorld().getY(),
|
||||||
getWorld().getX(), getWorld().getY() + 1) <= MAX_FACTORY_DISTANCE) {
|
getWorld().getX(), getWorld().getY() + 1) <= MAX_FACTORY_DISTANCE) {
|
||||||
if (!moveTo(8, 15, 0)) {
|
if (!moveTo(8, 15, 0)) {
|
||||||
setDirection(Direction.SOUTH);
|
setDirection(Direction.SOUTH);
|
||||||
@ -161,7 +168,7 @@ public abstract class NonPlayerCharacter extends GameObject implements Updatable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (direction == Direction.WEST) {
|
} else if (direction == Direction.WEST) {
|
||||||
if (Util.manhattanDist(factory.getWorld().getX(), factory.getWorld().getY(),
|
if (Util.manhattanDist(settlement.getWorld().getX(), settlement.getWorld().getY(),
|
||||||
getWorld().getX() - 1, getWorld().getY()) <= MAX_FACTORY_DISTANCE) {
|
getWorld().getX() - 1, getWorld().getY()) <= MAX_FACTORY_DISTANCE) {
|
||||||
if (!moveTo(0, 7, 0)) {
|
if (!moveTo(0, 7, 0)) {
|
||||||
setDirection(Direction.WEST);
|
setDirection(Direction.WEST);
|
||||||
@ -234,15 +241,15 @@ public abstract class NonPlayerCharacter extends GameObject implements Updatable
|
|||||||
return lastAction;
|
return lastAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Factory getFactory() {
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFactory(Factory factory) {
|
|
||||||
this.factory = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAge() {
|
public int getAge() {
|
||||||
return age;
|
return age;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Settlement getSettlement() {
|
||||||
|
return settlement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSettlement(Settlement settlement) {
|
||||||
|
this.settlement = settlement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
109
Plugin NPC/src/main/java/net/simon987/npcplugin/NpcBattery.java
Normal file
109
Plugin NPC/src/main/java/net/simon987/npcplugin/NpcBattery.java
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
public class NpcBattery extends HardwareModule {
|
||||||
|
|
||||||
|
public static final int DEFAULT_ADDRESS = 0x010A;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hardware ID (Should be unique)
|
||||||
|
*/
|
||||||
|
public static final char HWID = 0x010A;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Energy units in kJ
|
||||||
|
*/
|
||||||
|
private int energy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum energy units in kJ
|
||||||
|
*/
|
||||||
|
private int maxEnergy;
|
||||||
|
|
||||||
|
|
||||||
|
private static final int BATTERY_POLL = 1;
|
||||||
|
private static final int BATTERY_GET_MAX_CAPACITY = 2;
|
||||||
|
|
||||||
|
public NpcBattery(ControllableUnit unit) {
|
||||||
|
super(null, unit);
|
||||||
|
|
||||||
|
energy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy");
|
||||||
|
maxEnergy = GameServer.INSTANCE.getConfig().getInt("battery_max_energy");
|
||||||
|
}
|
||||||
|
|
||||||
|
public NpcBattery(Document document, ControllableUnit cubot) {
|
||||||
|
super(document, cubot);
|
||||||
|
|
||||||
|
energy = document.getInteger("energy");
|
||||||
|
maxEnergy = document.getInteger("max_energy");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleInterrupt(Status status) {
|
||||||
|
|
||||||
|
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||||
|
|
||||||
|
if (a == BATTERY_POLL) {
|
||||||
|
getCpu().getRegisterSet().getRegister("B").setValue(unit.getEnergy());
|
||||||
|
|
||||||
|
} else if (a == BATTERY_GET_MAX_CAPACITY) {
|
||||||
|
getCpu().getRegisterSet().getRegister("B").setValue(unit.getMaxEnergy());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getId() {
|
||||||
|
return HWID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject jsonSerialise() {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
|
||||||
|
json.put("energy", energy);
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject debugJsonSerialise() {
|
||||||
|
JSONObject json = jsonSerialise();
|
||||||
|
|
||||||
|
json.put("max_energy", maxEnergy);
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document document = super.mongoSerialise();
|
||||||
|
|
||||||
|
document.put("energy", energy);
|
||||||
|
document.put("max_energy", maxEnergy);
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEnergy() {
|
||||||
|
return energy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnergy(int energy) {
|
||||||
|
this.energy = energy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxEnergy() {
|
||||||
|
return maxEnergy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxEnergy(int maxEnergy) {
|
||||||
|
this.maxEnergy = maxEnergy;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.game.item.Item;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
|
||||||
|
public class NpcInventory extends HardwareModule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hardware ID (Should be unique)
|
||||||
|
*/
|
||||||
|
static final char HWID = 0x0106;
|
||||||
|
|
||||||
|
public static final int DEFAULT_ADDRESS = 0x0106;
|
||||||
|
|
||||||
|
private static final int INV_CLEAR = 0;
|
||||||
|
private static final int INV_POLL = 1;
|
||||||
|
private static final int INV_SCAN = 3;
|
||||||
|
|
||||||
|
private Item item;
|
||||||
|
|
||||||
|
public NpcInventory(ControllableUnit unit) {
|
||||||
|
super(null, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NpcInventory(Document document, ControllableUnit cubot) {
|
||||||
|
super(document, cubot);
|
||||||
|
|
||||||
|
Document itemDoc = (Document) document.get("item");
|
||||||
|
if (itemDoc != null) {
|
||||||
|
item = GameServer.INSTANCE.getRegistry().deserializeItem(itemDoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putItem(Item item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scanItem() {
|
||||||
|
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
|
item.digitize(unit.getCpu().getMemory(), x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Item clearItem() {
|
||||||
|
|
||||||
|
Item oldItem = item;
|
||||||
|
item.clear(unit);
|
||||||
|
item = null;
|
||||||
|
|
||||||
|
return oldItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getId() {
|
||||||
|
return HWID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Item getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleInterrupt(Status status) {
|
||||||
|
|
||||||
|
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||||
|
|
||||||
|
if (a == INV_POLL) {
|
||||||
|
char result;
|
||||||
|
if (item == null) {
|
||||||
|
result = 0;
|
||||||
|
} else {
|
||||||
|
result = item.poll();
|
||||||
|
}
|
||||||
|
getCpu().getRegisterSet().getRegister("B").setValue(result);
|
||||||
|
|
||||||
|
} else if (a == INV_CLEAR) {
|
||||||
|
if (unit.spendEnergy(100)) {
|
||||||
|
clearItem();
|
||||||
|
}
|
||||||
|
} else if (a == INV_SCAN) {
|
||||||
|
if (unit.spendEnergy(200)) {
|
||||||
|
scanItem();
|
||||||
|
clearItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document document = super.mongoSerialise();
|
||||||
|
|
||||||
|
if (item != null) {
|
||||||
|
document.put("item", item.mongoSerialise());
|
||||||
|
} else {
|
||||||
|
document.put("item", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("{NpcInventory [%s]}", item);
|
||||||
|
}
|
||||||
|
}
|
@ -1,65 +1,93 @@
|
|||||||
package net.simon987.npcplugin;
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.npcplugin.event.CpuInitialisationListener;
|
import net.simon987.npcplugin.event.CpuInitialisationListener;
|
||||||
|
import net.simon987.npcplugin.event.VaultCompleteListener;
|
||||||
|
import net.simon987.npcplugin.event.VaultWorldUpdateListener;
|
||||||
import net.simon987.npcplugin.event.WorldCreationListener;
|
import net.simon987.npcplugin.event.WorldCreationListener;
|
||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.npcplugin.world.TileVaultFloor;
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
import net.simon987.npcplugin.world.TileVaultWall;
|
||||||
import net.simon987.server.game.GameObject;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.io.CpuHardwareDeserializer;
|
import net.simon987.server.IServerConfiguration;
|
||||||
import net.simon987.server.io.GameObjectDeserializer;
|
import net.simon987.server.game.objects.GameRegistry;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import net.simon987.server.plugin.ServerPlugin;
|
import net.simon987.server.plugin.ServerPlugin;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class NpcPlugin extends ServerPlugin implements GameObjectDeserializer, CpuHardwareDeserializer {
|
public class NpcPlugin extends ServerPlugin {
|
||||||
|
|
||||||
/**
|
public static Map<String, Settlement> settlementMap;
|
||||||
* Radio tower cache
|
|
||||||
*/
|
public static Document DEFAULT_HACKED_NPC;
|
||||||
private static ArrayList<RadioTower> radioTowers;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServerConfiguration configuration) {
|
public void init(GameServer gameServer) {
|
||||||
|
|
||||||
listeners.add(new WorldCreationListener());
|
IServerConfiguration configuration = gameServer.getConfig();
|
||||||
|
GameRegistry registry = gameServer.getRegistry();
|
||||||
|
|
||||||
|
listeners.add(new WorldCreationListener(configuration.getInt("settlement_spawn_rate")));
|
||||||
listeners.add(new CpuInitialisationListener());
|
listeners.add(new CpuInitialisationListener());
|
||||||
|
listeners.add(new VaultWorldUpdateListener(configuration));
|
||||||
|
listeners.add(new VaultCompleteListener());
|
||||||
|
|
||||||
radioTowers = new ArrayList<>(32);
|
registry.registerGameObject(HarvesterNPC.class);
|
||||||
|
registry.registerGameObject(Factory.class);
|
||||||
|
registry.registerGameObject(RadioTower.class);
|
||||||
|
registry.registerGameObject(VaultDoor.class);
|
||||||
|
registry.registerGameObject(Obstacle.class);
|
||||||
|
registry.registerGameObject(ElectricBox.class);
|
||||||
|
registry.registerGameObject(Portal.class);
|
||||||
|
registry.registerGameObject(VaultExitPortal.class);
|
||||||
|
registry.registerGameObject(HackedNPC.class);
|
||||||
|
|
||||||
LogManager.LOGGER.info("Initialised NPC plugin");
|
registry.registerHardware(RadioReceiverHardware.class);
|
||||||
|
registry.registerHardware(NpcBattery.class);
|
||||||
|
registry.registerHardware(NpcInventory.class);
|
||||||
|
|
||||||
|
registry.registerTile(TileVaultFloor.ID, TileVaultFloor.class);
|
||||||
|
registry.registerTile(TileVaultWall.ID, TileVaultWall.class);
|
||||||
|
|
||||||
|
settlementMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
LogManager.LOGGER.fine("(NPC Plugin) Loading default HackedNPC settings from" +
|
||||||
|
" defaultHackedCubotHardware.json");
|
||||||
|
InputStream is = getClass().getClassLoader().getResourceAsStream("defaultHackedCubotHardware.json");
|
||||||
|
Scanner scanner = new Scanner(is).useDelimiter("\\A");
|
||||||
|
String json = scanner.next();
|
||||||
|
DEFAULT_HACKED_NPC = Document.parse(json);
|
||||||
|
|
||||||
|
LogManager.LOGGER.info("(NPC Plugin) Initialised NPC plugin");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GameObject deserializeObject(DBObject obj) {
|
public Document mongoSerialise() {
|
||||||
|
Document document = super.mongoSerialise();
|
||||||
|
|
||||||
int objType = (int) obj.get("t");
|
Document settlements = new Document();
|
||||||
|
for (String world : settlementMap.keySet()) {
|
||||||
if (objType == HarvesterNPC.ID) {
|
settlements.put(world, settlementMap.get(world).mongoSerialise());
|
||||||
return HarvesterNPC.deserialize(obj);
|
|
||||||
} else if (objType == Factory.ID) {
|
|
||||||
return Factory.deserialise(obj);
|
|
||||||
} else if (objType == RadioTower.ID) {
|
|
||||||
return RadioTower.deserialize(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
document.put("settlement_map", settlements);
|
||||||
|
|
||||||
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CpuHardware deserializeHardware(DBObject obj) {
|
public void load(Document document) {
|
||||||
int hwid = (int) obj.get("hwid");
|
super.load(document);
|
||||||
|
|
||||||
switch (hwid) {
|
Document settlements = (Document) document.get("settlement_map");
|
||||||
case RadioReceiverHardware.HWID:
|
|
||||||
return RadioReceiverHardware.deserialize(obj);
|
for (String world : settlements.keySet()) {
|
||||||
|
settlementMap.put(world, new Settlement((Document) settlements.get(world)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
LogManager.LOGGER.fine(String.format("(%s) Loaded %d settlements", name, settlementMap.size()));
|
||||||
}
|
|
||||||
|
|
||||||
public static ArrayList<RadioTower> getRadioTowers() {
|
|
||||||
return radioTowers;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
113
Plugin NPC/src/main/java/net/simon987/npcplugin/Obstacle.java
Normal file
113
Plugin NPC/src/main/java/net/simon987/npcplugin/Obstacle.java
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.game.objects.Attackable;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic game object that blocks the path.
|
||||||
|
*/
|
||||||
|
public class Obstacle extends GameObject implements Attackable {
|
||||||
|
|
||||||
|
public static final int MAP_INFO = 0x0701;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style of the obstacle. Will tell the client which sprite to display
|
||||||
|
*/
|
||||||
|
private int style = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current health of the npc
|
||||||
|
*/
|
||||||
|
private int hp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum health of the npc
|
||||||
|
*/
|
||||||
|
private int maxHp;
|
||||||
|
|
||||||
|
public Obstacle(int hp) {
|
||||||
|
this.hp = hp;
|
||||||
|
this.maxHp = hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Obstacle(Document document) {
|
||||||
|
super(document);
|
||||||
|
style = document.getInteger("style");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHealRate(int hp) {
|
||||||
|
//No op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void heal(int amount) {
|
||||||
|
//No op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHp() {
|
||||||
|
return hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHp(int hp) {
|
||||||
|
this.hp = hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxHp() {
|
||||||
|
return maxHp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxHp(int hp) {
|
||||||
|
this.maxHp = hp;
|
||||||
|
this.hp = hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void damage(int amount) {
|
||||||
|
hp -= amount;
|
||||||
|
|
||||||
|
//YOU ARE DEAD
|
||||||
|
if (hp <= 0) {
|
||||||
|
setDead(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getMapInfo() {
|
||||||
|
return MAP_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStyle() {
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStyle(int style) {
|
||||||
|
this.style = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document dbObject = super.mongoSerialise();
|
||||||
|
|
||||||
|
dbObject.put("hp", hp);
|
||||||
|
dbObject.put("style", style);
|
||||||
|
|
||||||
|
return dbObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject jsonSerialise() {
|
||||||
|
JSONObject json = super.jsonSerialise();
|
||||||
|
|
||||||
|
json.put("hp", hp);
|
||||||
|
json.put("style", style);
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
89
Plugin NPC/src/main/java/net/simon987/npcplugin/Portal.java
Normal file
89
Plugin NPC/src/main/java/net/simon987/npcplugin/Portal.java
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.game.objects.Enterable;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
import net.simon987.server.game.objects.Structure;
|
||||||
|
import net.simon987.server.game.objects.Updatable;
|
||||||
|
import net.simon987.server.game.world.Location;
|
||||||
|
import net.simon987.server.game.world.World;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
|
||||||
|
public class Portal extends Structure implements Enterable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destination location
|
||||||
|
*/
|
||||||
|
private Location destination;
|
||||||
|
|
||||||
|
public static final int MAP_INFO = 0x0801;
|
||||||
|
|
||||||
|
public Portal() {
|
||||||
|
super(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Portal(Document document) {
|
||||||
|
super(document, 1, 1);
|
||||||
|
|
||||||
|
destination = new Location(
|
||||||
|
document.getInteger("dstWorldX"),
|
||||||
|
document.getInteger("dstWorldY"),
|
||||||
|
document.getString("dstDimension"),
|
||||||
|
document.getInteger("dstX"),
|
||||||
|
document.getInteger("dstY"));
|
||||||
|
setX(document.getInteger("x"));
|
||||||
|
setY(document.getInteger("y"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an object attempts to walk directly into a Enterable object
|
||||||
|
*
|
||||||
|
* @param object The game object that attempted to enter
|
||||||
|
* @return true if successful, false to block the object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean enter(GameObject object) {
|
||||||
|
|
||||||
|
World world = GameServer.INSTANCE.getGameUniverse().getWorld(destination.worldX, destination.worldY, false, destination.dimension);
|
||||||
|
|
||||||
|
if (object instanceof Updatable) {
|
||||||
|
object.getWorld().decUpdatable();
|
||||||
|
world.incUpdatable();
|
||||||
|
}
|
||||||
|
object.getWorld().removeObject(object);
|
||||||
|
object.setWorld(world);
|
||||||
|
world.addObject(object);
|
||||||
|
|
||||||
|
object.setX(destination.x);
|
||||||
|
object.setY(destination.y);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getMapInfo() {
|
||||||
|
return MAP_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document dbObject = super.mongoSerialise();
|
||||||
|
|
||||||
|
dbObject.put("dstWorldX", destination.worldX);
|
||||||
|
dbObject.put("dstWorldY", destination.worldY);
|
||||||
|
dbObject.put("dstX", destination.x);
|
||||||
|
dbObject.put("dstY", destination.y);
|
||||||
|
dbObject.put("dstDimension", destination.dimension);
|
||||||
|
|
||||||
|
return dbObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getDestination() {
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDestination(Location destination) {
|
||||||
|
this.destination = destination;
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,16 @@
|
|||||||
package net.simon987.npcplugin;
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import net.simon987.server.assembly.HardwareModule;
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
|
||||||
import net.simon987.server.assembly.CpuHardware;
|
|
||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
import net.simon987.server.assembly.Util;
|
import net.simon987.server.assembly.Util;
|
||||||
import net.simon987.server.game.Action;
|
import net.simon987.server.game.objects.Action;
|
||||||
import net.simon987.server.game.ControllableUnit;
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class RadioReceiverHardware extends CpuHardware {
|
public class RadioReceiverHardware extends HardwareModule {
|
||||||
|
|
||||||
public static final char HWID = 0xC; //12
|
public static final char HWID = 0xC; //12
|
||||||
|
|
||||||
@ -25,6 +24,12 @@ public class RadioReceiverHardware extends CpuHardware {
|
|||||||
this.cubot = cubot;
|
this.cubot = cubot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RadioReceiverHardware(Document document, ControllableUnit unit) {
|
||||||
|
super(document, unit);
|
||||||
|
|
||||||
|
this.cubot = unit;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInterrupt(Status status) {
|
public void handleInterrupt(Status status) {
|
||||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||||
@ -35,12 +40,14 @@ public class RadioReceiverHardware extends CpuHardware {
|
|||||||
//Find the nearest Radio Tower and query it
|
//Find the nearest Radio Tower and query it
|
||||||
cubot.setAction(Action.LISTENING);
|
cubot.setAction(Action.LISTENING);
|
||||||
|
|
||||||
ArrayList<char[]> messages = new ArrayList<>(6);
|
List<char[]> messages = new ArrayList<>(6);
|
||||||
|
|
||||||
ArrayList<RadioTower> towers = new ArrayList<>(NpcPlugin.getRadioTowers()); //Avoid ConcurrentModificationException
|
for (String world : NpcPlugin.settlementMap.keySet()) {
|
||||||
for (RadioTower tower : towers) {
|
RadioTower tower = NpcPlugin.settlementMap.get(world).getRadioTower();
|
||||||
if (Util.manhattanDist(tower.getWorld().getX(), tower.getWorld().getY(), cubot.getWorld().getX(),
|
|
||||||
cubot.getWorld().getY()) <= RadioTower.MAX_RANGE) {
|
if (tower != null && Util.manhattanDist(
|
||||||
|
tower.getWorld().getX(), tower.getWorld().getY(),
|
||||||
|
cubot.getWorld().getX(), cubot.getWorld().getY()) <= RadioTower.MAX_RANGE) {
|
||||||
//Tower is in range
|
//Tower is in range
|
||||||
messages.addAll(tower.getMessages());
|
messages.addAll(tower.getMessages());
|
||||||
}
|
}
|
||||||
@ -67,17 +74,13 @@ public class RadioReceiverHardware extends CpuHardware {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public Document mongoSerialise() {
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
Document dbObject = new Document();
|
||||||
|
|
||||||
dbObject.put("hwid", (int) HWID);
|
dbObject.put("type", getClass().getCanonicalName());
|
||||||
dbObject.put("cubot", cubot.getObjectId());
|
dbObject.put("cubot", cubot.getObjectId());
|
||||||
|
|
||||||
return dbObject;
|
return dbObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RadioReceiverHardware deserialize(DBObject obj) {
|
|
||||||
return new RadioReceiverHardware((ControllableUnit) GameServer.INSTANCE.getGameUniverse().getObject((long) obj.get("cubot")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,36 @@
|
|||||||
package net.simon987.npcplugin;
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import net.simon987.server.GameServer;
|
||||||
import com.mongodb.DBObject;
|
import net.simon987.server.game.objects.MessageReceiver;
|
||||||
import net.simon987.server.game.GameObject;
|
import net.simon987.server.game.objects.Structure;
|
||||||
import net.simon987.server.game.Programmable;
|
import net.simon987.server.game.objects.Updatable;
|
||||||
import net.simon987.server.game.Updatable;
|
import org.bson.Document;
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class RadioTower extends GameObject implements Programmable, Updatable {
|
public class RadioTower extends Structure implements MessageReceiver, Updatable {
|
||||||
|
|
||||||
private static final int MAP_INFO = 0x1000;
|
private static final int MAP_INFO = 0x0901;
|
||||||
|
|
||||||
public static final int ID = 4;
|
public static final int MAX_RANGE = GameServer.INSTANCE.getConfig().getInt("radio_tower_range");
|
||||||
|
|
||||||
public static final int MAX_RANGE = 3; //todo load from config
|
|
||||||
|
|
||||||
private static final int MAX_MESSAGES = 16;
|
private static final int MAX_MESSAGES = 16;
|
||||||
|
|
||||||
|
public RadioTower() {
|
||||||
|
super(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RadioTower(Document document) {
|
||||||
|
super(document, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char getMapInfo() {
|
public char getMapInfo() {
|
||||||
return MAP_INFO;
|
return MAP_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Messages from the current tick
|
* Messages from the current tick
|
||||||
*/
|
*/
|
||||||
@ -53,68 +58,22 @@ public class RadioTower extends GameObject implements Programmable, Updatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
ArrayList<char[]> getMessages() {
|
||||||
public JSONObject serialise() {
|
|
||||||
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
|
|
||||||
json.put("i", getObjectId());
|
|
||||||
json.put("x", getX());
|
|
||||||
json.put("y", getY());
|
|
||||||
json.put("t", ID);
|
|
||||||
|
|
||||||
return json;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BasicDBObject mongoSerialise() {
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
|
||||||
|
|
||||||
dbObject.put("i", getObjectId());
|
|
||||||
dbObject.put("x", getX());
|
|
||||||
dbObject.put("y", getY());
|
|
||||||
dbObject.put("t", ID);
|
|
||||||
|
|
||||||
return dbObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RadioTower deserialize(DBObject obj) {
|
|
||||||
|
|
||||||
RadioTower tower = new RadioTower();
|
|
||||||
tower.setObjectId((long) obj.get("i"));
|
|
||||||
tower.setX((int) obj.get("x"));
|
|
||||||
tower.setY((int) obj.get("y"));
|
|
||||||
|
|
||||||
NpcPlugin.getRadioTowers().add(tower);
|
|
||||||
|
|
||||||
return tower;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public ArrayList<char[]> getMessages() {
|
|
||||||
return lastMessages;
|
return lastMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get the first directly adjacent tile (starting east, going clockwise)
|
public JSONObject debugJsonSerialise() {
|
||||||
*/
|
JSONObject json = super.debugJsonSerialise();
|
||||||
public Point getAdjacentTile() {
|
|
||||||
|
|
||||||
if (!getWorld().isTileBlocked(getX() + 1, getY())) {
|
JSONArray messages = new JSONArray();
|
||||||
return new Point(getX() + 1, getY());
|
|
||||||
|
|
||||||
} else if (!getWorld().isTileBlocked(getX(), getY() + 1)) {
|
for (char[] message : this.messages) {
|
||||||
return new Point(getX(), getY() + 1);
|
messages.add(new String(message));
|
||||||
|
|
||||||
} else if (!getWorld().isTileBlocked(getX() - 1, getY())) {
|
|
||||||
return new Point(getX() - 1, getY());
|
|
||||||
|
|
||||||
} else if (!getWorld().isTileBlocked(getX(), getY() - 1)) {
|
|
||||||
return new Point(getX(), getY() - 1);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json.put("messages", messages);
|
||||||
|
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
222
Plugin NPC/src/main/java/net/simon987/npcplugin/Settlement.java
Normal file
222
Plugin NPC/src/main/java/net/simon987/npcplugin/Settlement.java
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.game.world.TilePlain;
|
||||||
|
import net.simon987.server.game.world.World;
|
||||||
|
import net.simon987.server.game.world.WorldGenerationException;
|
||||||
|
import net.simon987.server.io.MongoSerializable;
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Settlement implements MongoSerializable {
|
||||||
|
|
||||||
|
private Factory factory = null;
|
||||||
|
private RadioTower radioTower = null;
|
||||||
|
private VaultDoor vaultDoor = null;
|
||||||
|
private World world;
|
||||||
|
private DifficultyLevel difficultyLevel;
|
||||||
|
|
||||||
|
private List<NonPlayerCharacter> npcs = new ArrayList<>();
|
||||||
|
|
||||||
|
private char[] password;
|
||||||
|
|
||||||
|
public Settlement(Document document) {
|
||||||
|
|
||||||
|
world = GameServer.INSTANCE.getGameUniverse().getWorld(document.getString("world"), false);
|
||||||
|
ObjectId radioTowerId = document.getObjectId("radio_tower");
|
||||||
|
if (radioTowerId != null) {
|
||||||
|
radioTower = (RadioTower) GameServer.INSTANCE.getGameUniverse().getObject(radioTowerId);
|
||||||
|
}
|
||||||
|
ObjectId vaultDoorId = document.getObjectId("vault_door");
|
||||||
|
if (vaultDoorId != null) {
|
||||||
|
vaultDoor = (VaultDoor) GameServer.INSTANCE.getGameUniverse().getObject(vaultDoorId);
|
||||||
|
}
|
||||||
|
ObjectId factoryId = document.getObjectId("factory");
|
||||||
|
factory = (Factory) GameServer.INSTANCE.getGameUniverse().getObject(factoryId);
|
||||||
|
|
||||||
|
difficultyLevel = DifficultyLevel.values()[document.getInteger("difficulty_level")];
|
||||||
|
|
||||||
|
Object[] npcArray = ((ArrayList) document.get("npcs")).toArray();
|
||||||
|
for (Object id : npcArray) {
|
||||||
|
|
||||||
|
NonPlayerCharacter npc = (NonPlayerCharacter) GameServer.INSTANCE.getGameUniverse().getObject((ObjectId) id);
|
||||||
|
|
||||||
|
if (npc != null) {
|
||||||
|
addNpc(npc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
password = document.getString("password").toCharArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Settlement(World world) throws WorldGenerationException {
|
||||||
|
|
||||||
|
this.world = world;
|
||||||
|
this.difficultyLevel = DifficultyLevel.NORMAL; //TODO randomize ?
|
||||||
|
this.password = "12345678".toCharArray();
|
||||||
|
|
||||||
|
outerLoopFactory:
|
||||||
|
for (int x = 2; x < 12; x++) {
|
||||||
|
for (int y = 2; y < 12; y++) {
|
||||||
|
|
||||||
|
if ((!world.isTileBlocked(x, y) && !world.isTileBlocked(x + 1, y) &&
|
||||||
|
!world.isTileBlocked(x, y + 1) && !world.isTileBlocked(x + 1, y + 1))) {
|
||||||
|
|
||||||
|
Factory factory = new Factory();
|
||||||
|
|
||||||
|
factory.setWorld(world);
|
||||||
|
factory.setObjectId(new ObjectId());
|
||||||
|
factory.setX(x);
|
||||||
|
factory.setY(y);
|
||||||
|
|
||||||
|
if (factory.getAdjacentTile() == null) {
|
||||||
|
//Factory has no non-blocked adjacent tiles
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.addObject(factory);
|
||||||
|
world.incUpdatable();
|
||||||
|
this.factory = factory;
|
||||||
|
|
||||||
|
break outerLoopFactory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (factory == null) {
|
||||||
|
throw new WorldGenerationException("Could not place Factory");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Also spawn a radio tower in the same World
|
||||||
|
Point p = world.getRandomTileWithAdjacent(8, TilePlain.ID);
|
||||||
|
if (p != null) {
|
||||||
|
while (p.x == 0 || p.x == world.getWorldSize() - 1 || p.y == world.getWorldSize() - 1 || p.y == 0) {
|
||||||
|
p = world.getRandomPassableTile();
|
||||||
|
|
||||||
|
if (p == null) {
|
||||||
|
//World is full
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RadioTower radioTower = new RadioTower();
|
||||||
|
|
||||||
|
radioTower.setWorld(world);
|
||||||
|
radioTower.setObjectId(new ObjectId());
|
||||||
|
radioTower.setX(p.x);
|
||||||
|
radioTower.setY(p.y);
|
||||||
|
|
||||||
|
if (radioTower.getAdjacentTile() != null) {
|
||||||
|
//Radio Tower has adjacent tiles
|
||||||
|
world.addObject(radioTower);
|
||||||
|
world.incUpdatable(); //In case the Factory couldn't be spawned.
|
||||||
|
|
||||||
|
this.radioTower = radioTower;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Also spawn a Vault in the same World
|
||||||
|
p = world.getRandomPassableTile();
|
||||||
|
if (p != null) {
|
||||||
|
|
||||||
|
VaultDoor vaultDoor = new VaultDoor();
|
||||||
|
vaultDoor.setWorld(world);
|
||||||
|
|
||||||
|
int counter = 700;
|
||||||
|
while (p.x == 0 || p.x == world.getWorldSize() - 1 || p.y == world.getWorldSize() - 1 || p.y == 0
|
||||||
|
|| vaultDoor.getAdjacentTileCount(true) < 8) {
|
||||||
|
p = world.getRandomPassableTile();
|
||||||
|
|
||||||
|
if (p == null) {
|
||||||
|
//World is full
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vaultDoor.setX(p.x);
|
||||||
|
vaultDoor.setY(p.y);
|
||||||
|
|
||||||
|
counter--;
|
||||||
|
|
||||||
|
if (counter <= 0) {
|
||||||
|
//Reached maximum amount of retries
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vaultDoor.setObjectId(new ObjectId());
|
||||||
|
world.addObject(vaultDoor);
|
||||||
|
world.incUpdatable(); //In case the Factory & Radio Tower couldn't be spawned.
|
||||||
|
vaultDoor.setWorld(world);
|
||||||
|
|
||||||
|
vaultDoor.initialize();
|
||||||
|
this.vaultDoor = vaultDoor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNpc(NonPlayerCharacter npc) {
|
||||||
|
npcs.add(npc);
|
||||||
|
npc.setSettlement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document document = new Document();
|
||||||
|
|
||||||
|
document.put("world", world.getId());
|
||||||
|
if (radioTower != null) {
|
||||||
|
document.put("radio_tower", radioTower.getObjectId());
|
||||||
|
}
|
||||||
|
if (vaultDoor != null) {
|
||||||
|
document.put("vault_door", vaultDoor.getObjectId());
|
||||||
|
}
|
||||||
|
document.put("factory", factory.getObjectId());
|
||||||
|
document.put("difficulty_level", difficultyLevel.ordinal());
|
||||||
|
document.put("password", String.valueOf(password));
|
||||||
|
|
||||||
|
|
||||||
|
List<ObjectId> npcArray = new ArrayList<>(npcs.size());
|
||||||
|
for (NonPlayerCharacter npc : npcs) {
|
||||||
|
npcArray.add(npc.getObjectId());
|
||||||
|
}
|
||||||
|
document.put("npcs", npcArray);
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DifficultyLevel {
|
||||||
|
NORMAL(0);
|
||||||
|
|
||||||
|
public int cypherId;
|
||||||
|
|
||||||
|
DifficultyLevel(int cypherId) {
|
||||||
|
this.cypherId = cypherId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Factory getFactory() {
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RadioTower getRadioTower() {
|
||||||
|
return radioTower;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VaultDoor getVaultDoor() {
|
||||||
|
return vaultDoor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public World getWorld() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<NonPlayerCharacter> getNpcs() {
|
||||||
|
return npcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[] getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,261 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.npcplugin.world.TileVaultFloor;
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.IServerConfiguration;
|
||||||
|
import net.simon987.server.game.objects.Direction;
|
||||||
|
import net.simon987.server.game.world.Location;
|
||||||
|
import net.simon987.server.game.world.World;
|
||||||
|
import net.simon987.server.logging.LogManager;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class VaultDimension {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the dimension
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private World homeWorld;
|
||||||
|
|
||||||
|
private int homeX;
|
||||||
|
private int homeY;
|
||||||
|
|
||||||
|
public VaultDimension(VaultDoor vaultDoor) {
|
||||||
|
|
||||||
|
name = "v" + vaultDoor.getObjectId();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a group of vault worlds and pieces them together with openings.
|
||||||
|
* For a set number of passes, a random number of vault worlds are added to each world in the
|
||||||
|
* previous 'layer' of worlds in a random direction. Openings are added to allow movement from a
|
||||||
|
* layer to the next, meaning that adjacent worlds are not necessarily connected, and one would
|
||||||
|
* necessarily need to travel through 5 openings to reach the 6th layer, even when that layer is
|
||||||
|
* less than 5 worlds away from the origin/home vault world (the one containing the exit door).
|
||||||
|
*
|
||||||
|
* 1. Create home world (layer 0)
|
||||||
|
* 2. For each world in the current layer, attach a random number of new worlds
|
||||||
|
* 3. Repeat the same step for the newly added layer
|
||||||
|
* 4. Choose a random world from the last layer and create the vault box there (objective)
|
||||||
|
* 5. Create an exit portal in the home world
|
||||||
|
*
|
||||||
|
* This process is done in 2 passes, in the first pass, worlds are defined
|
||||||
|
* as a set of coordinates + a list of opening directions, then they are actually generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
IServerConfiguration config = GameServer.INSTANCE.getConfig();
|
||||||
|
|
||||||
|
int minLayerCount = config.getInt("vault_wg_min_layer_count");
|
||||||
|
int maxLayerCount = config.getInt("vault_wg_max_layer_count");
|
||||||
|
int minAttachedWorld = config.getInt("vault_wg_min_attached_world");
|
||||||
|
int maxAttachedWorld = Math.min(config.getInt("vault_wg_max_attached_world"), 4);
|
||||||
|
int minElectricBoxCount = config.getInt("vault_wg_min_electric_box_count");
|
||||||
|
int maxElectricBoxCount = config.getInt("vault_wg_max_electric_box_count");
|
||||||
|
|
||||||
|
HashMap<Integer, ArrayList<WorldBluePrint>> worldLayers = new HashMap<>();
|
||||||
|
VaultWorldGenerator generator = new VaultWorldGenerator();
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
int layerCount = random.nextInt(maxLayerCount - minLayerCount) + minLayerCount;
|
||||||
|
|
||||||
|
//1. Create home world
|
||||||
|
WorldBluePrint homeWorldBluePrint = new WorldBluePrint();
|
||||||
|
homeWorldBluePrint.coords.x = 0x7FFF;
|
||||||
|
homeWorldBluePrint.coords.y = 0x7FFF;
|
||||||
|
worldLayers.put(0, new ArrayList<>());
|
||||||
|
worldLayers.get(0).add(homeWorldBluePrint);
|
||||||
|
|
||||||
|
//2. For each world in the current layer, attach a random number of new worlds
|
||||||
|
for (int i = 1; i <= layerCount; i++) {
|
||||||
|
|
||||||
|
worldLayers.put(i, new ArrayList<>());
|
||||||
|
|
||||||
|
for (WorldBluePrint world : worldLayers.get(i - 1)) {
|
||||||
|
|
||||||
|
int attachedWorlds;
|
||||||
|
if (i == 1) {
|
||||||
|
attachedWorlds = 4; // The home world should have 4 attached worlds
|
||||||
|
} else {
|
||||||
|
attachedWorlds = random.nextInt(maxAttachedWorld - minAttachedWorld) + minAttachedWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < attachedWorlds; j++) {
|
||||||
|
|
||||||
|
int randDirIndex = random.nextInt(4);
|
||||||
|
|
||||||
|
//Try 4 directions (wrap around 0..3)
|
||||||
|
for (int attemptCount = 0; attemptCount < 4; attemptCount++) {
|
||||||
|
Direction randomDirection = Direction.getDirection(randDirIndex);
|
||||||
|
|
||||||
|
//Don't attach a world at the same spot twice
|
||||||
|
if (!worldExists(world.coordinatesOf(randomDirection), worldLayers)) {
|
||||||
|
WorldBluePrint attachedWorld = world.attachWorld(randomDirection);
|
||||||
|
worldLayers.get(i).add(attachedWorld);
|
||||||
|
}
|
||||||
|
randDirIndex = (randDirIndex + 1) % 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<World> lastLayerWorlds = new ArrayList<>();
|
||||||
|
|
||||||
|
//Generate worlds
|
||||||
|
for (Integer key : worldLayers.keySet()) {
|
||||||
|
|
||||||
|
ArrayList<WorldBluePrint> layer = worldLayers.get(key);
|
||||||
|
|
||||||
|
for (WorldBluePrint bp : layer) {
|
||||||
|
World vWorld = generator.generateVaultWorld(bp.coords.x, bp.coords.y, bp.openings, name);
|
||||||
|
GameServer.INSTANCE.getGameUniverse().addWorld(vWorld);
|
||||||
|
|
||||||
|
ArrayList<ElectricBox> newBoxes = VaultWorldUtils.generateElectricBoxes(vWorld, minElectricBoxCount,
|
||||||
|
maxElectricBoxCount);
|
||||||
|
for (ElectricBox blob : newBoxes) {
|
||||||
|
vWorld.addObject(blob);
|
||||||
|
vWorld.incUpdatable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == layerCount) {
|
||||||
|
lastLayerWorlds.add(vWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == 0) {
|
||||||
|
this.homeWorld = vWorld;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Point exitCoords = vaultDoor.getAdjacentTile();
|
||||||
|
Location exitLocation = new Location(vaultDoor.getWorld().getX(), vaultDoor.getWorld().getY(), vaultDoor
|
||||||
|
.getWorld().getDimension(), exitCoords.x, exitCoords.y);
|
||||||
|
|
||||||
|
|
||||||
|
//4. Choose a random world from the last layer and create the vault box there (objective)
|
||||||
|
World objectiveWorld = lastLayerWorlds.get(random.nextInt(lastLayerWorlds.size()));
|
||||||
|
|
||||||
|
Point exitPortalPt = objectiveWorld.getRandomTileWithAdjacent(8, TileVaultFloor.ID);
|
||||||
|
|
||||||
|
if (exitPortalPt != null) {
|
||||||
|
|
||||||
|
VaultExitPortal exitPortal = new VaultExitPortal();
|
||||||
|
exitPortal.setDestination(exitLocation);
|
||||||
|
exitPortal.setX(exitPortalPt.x);
|
||||||
|
exitPortal.setY(exitPortalPt.y);
|
||||||
|
exitPortal.setWorld(objectiveWorld);
|
||||||
|
exitPortal.setObjectId(new ObjectId());
|
||||||
|
objectiveWorld.addObject(exitPortal);
|
||||||
|
|
||||||
|
// LogManager.LOGGER.severe("Objective: " + objectiveWorld.getId());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LogManager.LOGGER.severe("FIXME: Couldn't create exit portal for world " + homeWorld.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
//5. Create an exit portal in the home World
|
||||||
|
Point homePortalPt = homeWorld.getRandomTileWithAdjacent(8, TileVaultFloor.ID);
|
||||||
|
if (homePortalPt != null) {
|
||||||
|
|
||||||
|
Portal homePortal = new Portal();
|
||||||
|
homePortal.setDestination(exitLocation);
|
||||||
|
homePortal.setX(homePortalPt.x);
|
||||||
|
homePortal.setY(homePortalPt.y);
|
||||||
|
homePortal.setWorld(homeWorld);
|
||||||
|
homePortal.setObjectId(new ObjectId());
|
||||||
|
homeWorld.addObject(homePortal);
|
||||||
|
|
||||||
|
Point entryCoords = homePortal.getAdjacentTile();
|
||||||
|
homeX = entryCoords.x;
|
||||||
|
homeY = entryCoords.y;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LogManager.LOGGER.severe("FIXME: Couldn't create home exit portal for world " + homeWorld.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean worldExists(Point coords, HashMap<Integer, ArrayList<WorldBluePrint>> worldLayers) {
|
||||||
|
|
||||||
|
//Auto-generated by IntelliJ Idea
|
||||||
|
return worldLayers.values().stream().flatMap(Collection::stream).anyMatch(bp -> bp.coords.equals(coords));
|
||||||
|
}
|
||||||
|
|
||||||
|
World getHomeWorld() {
|
||||||
|
return homeWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHomeX() {
|
||||||
|
return homeX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHomeY() {
|
||||||
|
return homeY;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Helper class to plan the layout of a vault dimension
|
||||||
|
*/
|
||||||
|
private class WorldBluePrint {
|
||||||
|
|
||||||
|
ArrayList<Direction> openings = new ArrayList<>(4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coordinates of the world
|
||||||
|
*/
|
||||||
|
Point coords = new Point();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the blueprint's openings to allow traveling to the newly attached world
|
||||||
|
*
|
||||||
|
* @param direction direction of the world to attach (relative to this one)
|
||||||
|
* @return The blueprint of the attached world
|
||||||
|
*/
|
||||||
|
WorldBluePrint attachWorld(Direction direction) {
|
||||||
|
|
||||||
|
WorldBluePrint attachedWorld = new WorldBluePrint();
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case NORTH:
|
||||||
|
openings.add(Direction.NORTH);
|
||||||
|
attachedWorld.openings.add(Direction.SOUTH);
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
openings.add(Direction.EAST);
|
||||||
|
attachedWorld.openings.add(Direction.WEST);
|
||||||
|
break;
|
||||||
|
case SOUTH:
|
||||||
|
openings.add(Direction.SOUTH);
|
||||||
|
attachedWorld.openings.add(Direction.NORTH);
|
||||||
|
break;
|
||||||
|
case WEST:
|
||||||
|
openings.add(Direction.WEST);
|
||||||
|
attachedWorld.openings.add(Direction.EAST);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
attachedWorld.coords.x = coords.x + direction.dX;
|
||||||
|
attachedWorld.coords.y = coords.y + direction.dY;
|
||||||
|
|
||||||
|
return attachedWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the coordinates of a world that would be attached to this world
|
||||||
|
*
|
||||||
|
* @param direction direction of the attached world
|
||||||
|
*/
|
||||||
|
Point coordinatesOf(Direction direction) {
|
||||||
|
|
||||||
|
return new Point(coords.x + direction.dX, coords.y + direction.dY);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
164
Plugin NPC/src/main/java/net/simon987/npcplugin/VaultDoor.java
Normal file
164
Plugin NPC/src/main/java/net/simon987/npcplugin/VaultDoor.java
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.game.objects.*;
|
||||||
|
import net.simon987.server.game.world.World;
|
||||||
|
import net.simon987.server.logging.LogManager;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
|
||||||
|
public class VaultDoor extends Structure implements MessageReceiver, Enterable, Updatable {
|
||||||
|
|
||||||
|
private static final int MAP_INFO = 0x0B00;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the vault door is opened
|
||||||
|
*/
|
||||||
|
private boolean open = false;
|
||||||
|
|
||||||
|
private int homeX;
|
||||||
|
private int homeY;
|
||||||
|
private World homeWorld;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of ticks to remain the door open
|
||||||
|
*/
|
||||||
|
private int OPEN_TIME = GameServer.INSTANCE.getConfig().getInt("vault_door_open_time");
|
||||||
|
|
||||||
|
private int openedTimer = 0;
|
||||||
|
|
||||||
|
public VaultDoor() {
|
||||||
|
super(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VaultDoor(Document document) {
|
||||||
|
super(document, 1, 1);
|
||||||
|
|
||||||
|
setX(document.getInteger("x"));
|
||||||
|
setY(document.getInteger("y"));
|
||||||
|
|
||||||
|
|
||||||
|
if (document.containsKey("homeX") && document.containsKey("homeY")) {
|
||||||
|
homeX = document.getInteger("homeX");
|
||||||
|
homeY = document.getInteger("homeY");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
if (open){
|
||||||
|
if (openedTimer <= 0) {
|
||||||
|
//Door was open for OPEN_TIME, close it
|
||||||
|
open = false;
|
||||||
|
openedTimer = 0;
|
||||||
|
LogManager.LOGGER.fine("Closed Vault door ID: " + getObjectId());
|
||||||
|
} else {
|
||||||
|
openedTimer--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean sendMessage(char[] message) {
|
||||||
|
|
||||||
|
Settlement settlement = NpcPlugin.settlementMap.get(getWorld().getId());
|
||||||
|
|
||||||
|
System.out.println("message: " + new String(message));
|
||||||
|
System.out.println("password: " + new String(settlement.getPassword()));
|
||||||
|
|
||||||
|
if (Arrays.equals(message, settlement.getPassword())) {
|
||||||
|
if (!open) {
|
||||||
|
openVault();
|
||||||
|
} else {
|
||||||
|
keepVaultOpen();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openVault() {
|
||||||
|
open = true;
|
||||||
|
openedTimer = OPEN_TIME;
|
||||||
|
LogManager.LOGGER.fine("Opened Vault door ID: " + getObjectId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void keepVaultOpen() {
|
||||||
|
open = true;
|
||||||
|
openedTimer = OPEN_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean enter(GameObject object) {
|
||||||
|
|
||||||
|
// LogManager.LOGGER.fine("VAULT enter " + open);
|
||||||
|
|
||||||
|
if (open) {
|
||||||
|
|
||||||
|
object.getWorld().decUpdatable();
|
||||||
|
object.getWorld().removeObject(object);
|
||||||
|
|
||||||
|
homeWorld.incUpdatable();
|
||||||
|
homeWorld.addObject(object);
|
||||||
|
object.setWorld(homeWorld);
|
||||||
|
object.setX(homeX);
|
||||||
|
object.setY(homeY);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getMapInfo() {
|
||||||
|
return MAP_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document dbObject = super.mongoSerialise();
|
||||||
|
|
||||||
|
dbObject.put("homeX", getHomeX());
|
||||||
|
dbObject.put("homeY", getHomeY());
|
||||||
|
|
||||||
|
return dbObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
//Get or generate vault world
|
||||||
|
homeWorld = GameServer.INSTANCE.getGameUniverse().getWorld(0x7FFF, 0x7FFF,
|
||||||
|
false, "v" + getObjectId() + "-");
|
||||||
|
|
||||||
|
if (homeWorld == null) {
|
||||||
|
VaultDimension vaultDimension = new VaultDimension(this);
|
||||||
|
homeWorld = vaultDimension.getHomeWorld();
|
||||||
|
homeX = vaultDimension.getHomeX();
|
||||||
|
homeY = vaultDimension.getHomeY();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHomeX() {
|
||||||
|
return homeX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHomeX(int homeX) {
|
||||||
|
this.homeX = homeX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHomeY() {
|
||||||
|
return homeY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHomeY(int homeY) {
|
||||||
|
this.homeY = homeY;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
import net.simon987.server.game.world.Location;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Final exit portal located in the 'last' World of a Vault dimension
|
||||||
|
*/
|
||||||
|
public class VaultExitPortal extends Portal {
|
||||||
|
|
||||||
|
public VaultExitPortal() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public VaultExitPortal(Document document) {
|
||||||
|
super(document);
|
||||||
|
|
||||||
|
setDestination(new Location(
|
||||||
|
document.getInteger("dstWorldX"),
|
||||||
|
document.getInteger("dstWorldY"),
|
||||||
|
document.getString("dstDimension"),
|
||||||
|
document.getInteger("dstX"),
|
||||||
|
document.getInteger("dstY")));
|
||||||
|
setX(document.getInteger("x"));
|
||||||
|
setY(document.getInteger("y"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean enter(GameObject object) {
|
||||||
|
|
||||||
|
//TODO: Trigger vault complete event instead
|
||||||
|
return super.enter(object);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,265 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.game.objects.Direction;
|
||||||
|
import net.simon987.server.game.world.TileMap;
|
||||||
|
import net.simon987.server.game.world.TileVoid;
|
||||||
|
import net.simon987.server.game.world.World;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class VaultWorldGenerator {
|
||||||
|
|
||||||
|
public World generateVaultWorld(int worldX, int worldY, ArrayList<Direction> openings, String dimension) {
|
||||||
|
|
||||||
|
// LogManager.LOGGER.info("Generating vault World");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Openings are always at the same spot (marked by '?')
|
||||||
|
* 1. Rectangles of random size are generated
|
||||||
|
* 2. Openings are generated (if another vault world is connected on this direction)
|
||||||
|
* 3. They are connected with tunnels from bottom to top,
|
||||||
|
* by their roomCenter, alternating between horizontal first
|
||||||
|
* tunnels and vertical first
|
||||||
|
* 4. Tiles adjacent to floor tiles are set to wall tiles
|
||||||
|
* Example map:
|
||||||
|
*
|
||||||
|
* # # # # # # # - - - # ? ? # - - - - - - - - - -
|
||||||
|
* # o o o o o # - - - # ? ? # - - - - - - - - - -
|
||||||
|
* # o o o o o # # # # # # o # - - - - - - - - - -
|
||||||
|
* # o o o o o o o o o o o o # - - - - - - - - - -
|
||||||
|
* # o o o o o # # # # # # # # # # # - - - - - - -
|
||||||
|
* # o o o o o # - - - - # o o o o # - - - - - - -
|
||||||
|
* # o o o o o # # # # # # o o o o # - - - - - - -
|
||||||
|
* # # o o o o o o o o o o o o o o # - - - - - - -
|
||||||
|
* - # o # # # # # # # # # o o o o # - - - - - - -
|
||||||
|
* - # o # - - - - - - - # # # # # # - - - - - - -
|
||||||
|
* # # o # - - - - - - - - - - - - - - - - - # # #
|
||||||
|
* ? ? o # # # # # # # # # # # # # # # # # # # ? ?
|
||||||
|
* ? ? o o o o o o o o o o o o o o o o o o o o ? ?
|
||||||
|
* # # # # # # # # # # # # # # # # # # o # # # # #
|
||||||
|
* - - - - - - - - - - - - - - - - - # o # - - - -
|
||||||
|
* - # # # # # # # # # - - - - - - - # o # - - - -
|
||||||
|
* - # o o o o o o o # - - - # # # # # o # # # # -
|
||||||
|
* - # o o o o o o o # # # # # o o o o o o o o # -
|
||||||
|
* - # o o o o o o o o o o o # o o o o o o o o # -
|
||||||
|
* - # o o o o o o o # # # o # o o o o o o o o # -
|
||||||
|
* - # o o o o o o o # - # o # # # # # # # # # # -
|
||||||
|
* - # o o o o o o o # # # o # - - - - - - - - - -
|
||||||
|
* - # # # # # # # # # # ? ? # - - - - - - - - - -
|
||||||
|
* - - - - - - - - - - # ? ? # - - - - - - - - - -
|
||||||
|
*/
|
||||||
|
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
int worldSize = 20;
|
||||||
|
int floorTile = 4;
|
||||||
|
int wallTile = 5;
|
||||||
|
int minRoomCount = 5;
|
||||||
|
int maxRoomCount = 8;
|
||||||
|
int minRoomWidth = 4;
|
||||||
|
int minRoomHeight = 4;
|
||||||
|
int maxRoomWidth = 8;
|
||||||
|
int maxRoomHeight = 8;
|
||||||
|
|
||||||
|
ArrayList<Point> roomCenters = new ArrayList<>(maxRoomCount + 4);
|
||||||
|
ArrayList<Rectangle> rooms = new ArrayList<>(maxRoomCount);
|
||||||
|
|
||||||
|
World world = new World(worldX, worldY, new TileMap(worldSize, worldSize), dimension);
|
||||||
|
|
||||||
|
TileMap map = world.getTileMap();
|
||||||
|
|
||||||
|
//Generate rectangles of random size
|
||||||
|
int roomCount = random.nextInt(maxRoomCount - minRoomCount) + minRoomCount;
|
||||||
|
|
||||||
|
for (int i = 0; i < roomCount; i++) {
|
||||||
|
|
||||||
|
int roomWidth = random.nextInt(maxRoomWidth - minRoomWidth) + minRoomWidth;
|
||||||
|
int roomHeight = random.nextInt(maxRoomHeight - minRoomHeight) + minRoomHeight;
|
||||||
|
|
||||||
|
int attempts = 35;
|
||||||
|
Point roomCorner;
|
||||||
|
Rectangle room = null;
|
||||||
|
|
||||||
|
//Try to find a spot that doesn't intersect another room
|
||||||
|
attemptsLoop:
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
if (attempts < 0) {
|
||||||
|
roomCorner = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
roomCorner = new Point(random.nextInt((worldSize - roomWidth) - 2) + 2,
|
||||||
|
random.nextInt((worldSize - roomHeight) - 2) + 2);
|
||||||
|
|
||||||
|
room = new Rectangle(roomCorner.x, roomCorner.y, roomWidth, roomHeight);
|
||||||
|
|
||||||
|
for (Rectangle otherRoom : rooms) {
|
||||||
|
if (otherRoom.intersects(room)) {
|
||||||
|
attempts--;
|
||||||
|
continue attemptsLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roomCorner != null) {
|
||||||
|
for (int x = roomCorner.x; x < roomCorner.x + roomWidth; x++) {
|
||||||
|
for (int y = roomCorner.y; y < roomCorner.y + roomHeight; y++) {
|
||||||
|
map.setTileAt(floorTile, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rooms.add(room);
|
||||||
|
roomCenters.add(new Point(roomCorner.x + roomWidth / 2, roomCorner.y + roomHeight / 2));
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create openings
|
||||||
|
for (Direction opening : openings) {
|
||||||
|
switch (opening) {
|
||||||
|
case NORTH:
|
||||||
|
|
||||||
|
map.setTileAt(floorTile, worldSize / 2, 0);
|
||||||
|
map.setTileAt(floorTile, worldSize / 2, 1);
|
||||||
|
map.setTileAt(floorTile, worldSize / 2 - 1, 0);
|
||||||
|
map.setTileAt(floorTile, worldSize / 2 - 1, 1);
|
||||||
|
roomCenters.add(new Point(worldSize / 2, 1));
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
|
||||||
|
map.setTileAt(floorTile, worldSize - 1, worldSize / 2);
|
||||||
|
map.setTileAt(floorTile, worldSize - 1, worldSize / 2 - 1);
|
||||||
|
map.setTileAt(floorTile, worldSize - 2, worldSize / 2);
|
||||||
|
map.setTileAt(floorTile, worldSize - 2, worldSize / 2 - 1);
|
||||||
|
roomCenters.add(new Point(worldSize - 2, worldSize / 2 - 1));
|
||||||
|
break;
|
||||||
|
case SOUTH:
|
||||||
|
|
||||||
|
map.setTileAt(floorTile, worldSize / 2, worldSize - 1);
|
||||||
|
map.setTileAt(floorTile, worldSize / 2, worldSize - 2);
|
||||||
|
map.setTileAt(floorTile, worldSize / 2 - 1, worldSize - 1);
|
||||||
|
map.setTileAt(floorTile, worldSize / 2 - 1, worldSize - 2);
|
||||||
|
roomCenters.add(new Point(worldSize / 2, worldSize - 2));
|
||||||
|
break;
|
||||||
|
case WEST:
|
||||||
|
|
||||||
|
map.setTileAt(floorTile, 0, worldSize / 2);
|
||||||
|
map.setTileAt(floorTile, 0, worldSize / 2 - 1);
|
||||||
|
map.setTileAt(floorTile, 1, worldSize / 2);
|
||||||
|
map.setTileAt(floorTile, 1, worldSize / 2 - 1);
|
||||||
|
roomCenters.add(new Point(1, worldSize / 2 - 1));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Connect rooms together, from bottom to top
|
||||||
|
roomCenters.sort(new RoomCenterComparator());
|
||||||
|
boolean xFirst = true; //Start the tunnel horizontally
|
||||||
|
|
||||||
|
for (int i = 0; i < roomCenters.size() - 1; i++) {
|
||||||
|
//Note to self: I wouldn't bother trying to understand what's in this for loop,
|
||||||
|
//If this needs to be modified just trash it and start over
|
||||||
|
|
||||||
|
if (xFirst) {
|
||||||
|
if (roomCenters.get(i + 1).x - roomCenters.get(i).x < 0) {
|
||||||
|
for (int x = roomCenters.get(i).x; x > roomCenters.get(i + 1).x; x--) {
|
||||||
|
map.setTileAt(floorTile, x, roomCenters.get(i).y);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int x = roomCenters.get(i).x; x < roomCenters.get(i + 1).x; x++) {
|
||||||
|
map.setTileAt(floorTile, x, roomCenters.get(i).y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roomCenters.get(i + 1).y - roomCenters.get(i).y < 0) {
|
||||||
|
for (int y = roomCenters.get(i).y; y > roomCenters.get(i + 1).y; y--) {
|
||||||
|
map.setTileAt(floorTile, roomCenters.get(i + 1).x, y);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int y = roomCenters.get(i).y; y < roomCenters.get(i + 1).y; y++) {
|
||||||
|
map.setTileAt(floorTile, roomCenters.get(i + 1).x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (roomCenters.get(i + 1).x - roomCenters.get(i).x < 0) {
|
||||||
|
for (int x = roomCenters.get(i).x; x > roomCenters.get(i + 1).x; x--) {
|
||||||
|
map.setTileAt(floorTile, x, roomCenters.get(i + 1).y);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int x = roomCenters.get(i).x; x < roomCenters.get(i + 1).x; x++) {
|
||||||
|
map.setTileAt(floorTile, x, roomCenters.get(i + 1).y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roomCenters.get(i + 1).y - roomCenters.get(i).y < 0) {
|
||||||
|
for (int y = roomCenters.get(i).y; y > roomCenters.get(i + 1).y; y--) {
|
||||||
|
map.setTileAt(floorTile, roomCenters.get(i).x, y);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int y = roomCenters.get(i).y; y < roomCenters.get(i + 1).y; y++) {
|
||||||
|
map.setTileAt(floorTile, roomCenters.get(i).x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xFirst = !xFirst;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Tiles adjacent to floor tiles are set to wall tiles
|
||||||
|
for (int x = 0; x < worldSize; x++) {
|
||||||
|
for (int y = 0; y < worldSize; y++) {
|
||||||
|
|
||||||
|
if (map.getTileIdAt(x, y) != floorTile && hasTileAdjacent(x, y, map, floorTile)) {
|
||||||
|
map.setTileAt(wallTile, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set other tiles to 'void'
|
||||||
|
for (int x = 0; x < worldSize; x++) {
|
||||||
|
for (int y = 0; y < worldSize; y++) {
|
||||||
|
|
||||||
|
if (map.getTileIdAt(x, y) != floorTile && map.getTileIdAt(x, y) != wallTile) {
|
||||||
|
map.setTileAt(new TileVoid(), x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return world;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasTileAdjacent(int x, int y, TileMap map, int tile) {
|
||||||
|
|
||||||
|
for (int dX = -1; dX <= 1; dX++) {
|
||||||
|
for (int dY = -1; dY <= 1; dY++) {
|
||||||
|
|
||||||
|
if (map.getTileIdAt(x + dX, y + dY) == tile) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RoomCenterComparator implements Comparator<Point> {
|
||||||
|
@Override
|
||||||
|
public int compare(Point o1, Point o2) {
|
||||||
|
return o1.y - o2.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package net.simon987.npcplugin;
|
||||||
|
|
||||||
|
import net.simon987.npcplugin.world.TileVaultFloor;
|
||||||
|
import net.simon987.server.game.world.TileMap;
|
||||||
|
import net.simon987.server.game.world.World;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class VaultWorldUtils {
|
||||||
|
|
||||||
|
|
||||||
|
public static ArrayList<ElectricBox> generateElectricBoxes(World world, int minCount, int maxCount) {
|
||||||
|
|
||||||
|
Random random = new Random();
|
||||||
|
int boxesCount = random.nextInt(maxCount - minCount) + minCount;
|
||||||
|
ArrayList<ElectricBox> electricBoxes = new ArrayList<>(boxesCount);
|
||||||
|
|
||||||
|
//Count number of floor tiles. If there is less plain tiles than desired amount of boxes,
|
||||||
|
//set the desired amount of blobs to the plain tile count
|
||||||
|
TileMap m = world.getTileMap();
|
||||||
|
int floorCount = 0;
|
||||||
|
for (int y = 0; y < world.getWorldSize(); y++) {
|
||||||
|
for (int x = 0; x < world.getWorldSize(); x++) {
|
||||||
|
|
||||||
|
if (m.getTileIdAt(x, y) == TileVaultFloor.ID) {
|
||||||
|
floorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boxesCount > floorCount) {
|
||||||
|
boxesCount = floorCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
outerLoop:
|
||||||
|
for (int i = 0; i < boxesCount; i++) {
|
||||||
|
|
||||||
|
Point p = m.getRandomTile(TileVaultFloor.ID);
|
||||||
|
if (p != null) {
|
||||||
|
|
||||||
|
//Don't block worlds
|
||||||
|
int counter = 0;
|
||||||
|
while (p.x == 0 || p.y == 0 || p.x == world.getWorldSize() - 1 || p.y == world.getWorldSize() - 1 ||
|
||||||
|
world.getGameObjectsAt(p.x, p.y).size() != 0) {
|
||||||
|
p = m.getRandomTile(TileVaultFloor.ID);
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
if (counter > 25) {
|
||||||
|
continue outerLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ElectricBox box : electricBoxes) {
|
||||||
|
if (box.getX() == p.x && box.getY() == p.y) {
|
||||||
|
//There is already a box here
|
||||||
|
continue outerLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElectricBox box = new ElectricBox();
|
||||||
|
box.setObjectId(new ObjectId());
|
||||||
|
box.setX(p.x);
|
||||||
|
box.setY(p.y);
|
||||||
|
box.setWorld(world);
|
||||||
|
|
||||||
|
electricBoxes.add(box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return electricBoxes;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,8 @@ import net.simon987.server.assembly.CPU;
|
|||||||
import net.simon987.server.event.CpuInitialisationEvent;
|
import net.simon987.server.event.CpuInitialisationEvent;
|
||||||
import net.simon987.server.event.GameEvent;
|
import net.simon987.server.event.GameEvent;
|
||||||
import net.simon987.server.event.GameEventListener;
|
import net.simon987.server.event.GameEventListener;
|
||||||
import net.simon987.server.user.User;
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import net.simon987.server.game.objects.HardwareHost;
|
||||||
|
|
||||||
public class CpuInitialisationListener implements GameEventListener {
|
public class CpuInitialisationListener implements GameEventListener {
|
||||||
@Override
|
@Override
|
||||||
@ -17,11 +18,12 @@ public class CpuInitialisationListener implements GameEventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void handle(GameEvent event) {
|
public void handle(GameEvent event) {
|
||||||
CPU cpu = (CPU) event.getSource();
|
CPU cpu = (CPU) event.getSource();
|
||||||
User user = ((CpuInitialisationEvent) event).getUser();
|
ControllableUnit controllableUnit = ((CpuInitialisationEvent) event).getUnit();
|
||||||
|
cpu.setHardwareHost((HardwareHost) controllableUnit);
|
||||||
|
|
||||||
RadioReceiverHardware radioHw = new RadioReceiverHardware(user.getControlledUnit());
|
RadioReceiverHardware radioHw = new RadioReceiverHardware(controllableUnit);
|
||||||
radioHw.setCpu(cpu);
|
radioHw.setCpu(cpu);
|
||||||
|
|
||||||
cpu.attachHardware(radioHw, RadioReceiverHardware.DEFAULT_ADDRESS);
|
cpu.getHardwareHost().attachHardware(radioHw, RadioReceiverHardware.DEFAULT_ADDRESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package net.simon987.npcplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.npcplugin.VaultExitPortal;
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
|
||||||
|
public class VaultCompleteEvent extends GameEvent {
|
||||||
|
|
||||||
|
private VaultExitPortal portal;
|
||||||
|
|
||||||
|
public VaultCompleteEvent(GameObject object, VaultExitPortal portal) {
|
||||||
|
|
||||||
|
//TODO: Add completion time?
|
||||||
|
setSource(object);
|
||||||
|
this.portal = portal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GameObject getSource() {
|
||||||
|
return (GameObject) super.getSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
public VaultExitPortal getPortal() {
|
||||||
|
return portal;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package net.simon987.npcplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.event.GameEventListener;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
import net.simon987.server.logging.LogManager;
|
||||||
|
|
||||||
|
public class VaultCompleteListener implements GameEventListener {
|
||||||
|
@Override
|
||||||
|
public Class getListenedEventType() {
|
||||||
|
return VaultCompleteEvent.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(GameEvent event) {
|
||||||
|
VaultCompleteEvent vaultCompleteEvent = (VaultCompleteEvent) event;
|
||||||
|
GameObject object = vaultCompleteEvent.getSource();
|
||||||
|
if (object instanceof ControllableUnit) {
|
||||||
|
LogManager.LOGGER.info(((ControllableUnit) object).getParent().getUsername() + " Completed vault " +
|
||||||
|
object.getWorld().getDimension());
|
||||||
|
|
||||||
|
((ControllableUnit) object).getParent().getStats().addToStringSet("completedVaults",
|
||||||
|
vaultCompleteEvent.getPortal().getWorld().getDimension());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
package net.simon987.npcplugin.event;
|
||||||
|
|
||||||
|
import net.simon987.npcplugin.ElectricBox;
|
||||||
|
import net.simon987.npcplugin.VaultWorldUtils;
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.IServerConfiguration;
|
||||||
|
import net.simon987.server.event.GameEvent;
|
||||||
|
import net.simon987.server.event.GameEventListener;
|
||||||
|
import net.simon987.server.event.WorldUpdateEvent;
|
||||||
|
import net.simon987.server.game.world.World;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class VaultWorldUpdateListener implements GameEventListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of worlds and their time to wait until next respawn event
|
||||||
|
*/
|
||||||
|
private HashMap<World, Long> worldWaitMap = new HashMap<>(200);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lower bound of ElectricBox to be created on a respawn event
|
||||||
|
*/
|
||||||
|
private static int minElectricBoxCount;
|
||||||
|
/**
|
||||||
|
* Upper bound of ElectricBox to be created on a respawn event
|
||||||
|
*/
|
||||||
|
private static int maxElectricBoxCount;
|
||||||
|
/**
|
||||||
|
* Number of game ticks to wait after the threshold has been met
|
||||||
|
*/
|
||||||
|
private static int waitTime;
|
||||||
|
/**
|
||||||
|
* Threshold before starting the
|
||||||
|
*/
|
||||||
|
private static int electricBoxThreshold;
|
||||||
|
|
||||||
|
public VaultWorldUpdateListener(IServerConfiguration config) {
|
||||||
|
|
||||||
|
minElectricBoxCount = config.getInt("min_electric_box_respawn_count");
|
||||||
|
maxElectricBoxCount = config.getInt("max_electric_box_respawn_count");
|
||||||
|
waitTime = config.getInt("electric_box_respawnTime");
|
||||||
|
electricBoxThreshold = config.getInt("min_electric_box_count");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getListenedEventType() {
|
||||||
|
return WorldUpdateEvent.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(GameEvent event) {
|
||||||
|
|
||||||
|
//TODO: Move this and the Biomass UpdateListener to a 'RespawnManager' kind of deal
|
||||||
|
World world = ((WorldUpdateEvent) event).getWorld();
|
||||||
|
|
||||||
|
if (world.getDimension().startsWith("v")) {
|
||||||
|
//If there is less than the respawn threshold,
|
||||||
|
if (world.findObjects(ElectricBox.class).size() < electricBoxThreshold) {
|
||||||
|
|
||||||
|
//Set a timer for respawn_time ticks
|
||||||
|
if (!worldWaitMap.containsKey(world) || worldWaitMap.get(world) == 0L) {
|
||||||
|
worldWaitMap.put(world, GameServer.INSTANCE.getGameUniverse().getTime() + waitTime);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
long waitUntil = worldWaitMap.get(world);
|
||||||
|
|
||||||
|
if (GameServer.INSTANCE.getGameUniverse().getTime() >= waitUntil) {
|
||||||
|
|
||||||
|
//If the timer was set less than respawn_time ticks ago, respawn the blobs
|
||||||
|
ArrayList<ElectricBox> newBoxes = VaultWorldUtils.generateElectricBoxes(world, minElectricBoxCount,
|
||||||
|
maxElectricBoxCount);
|
||||||
|
for (ElectricBox blob : newBoxes) {
|
||||||
|
world.addObject(blob);
|
||||||
|
world.incUpdatable();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set the 'waitUntil' time to 0 to indicate that we are not waiting
|
||||||
|
worldWaitMap.replace(world, 0L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,14 @@
|
|||||||
package net.simon987.npcplugin.event;
|
package net.simon987.npcplugin.event;
|
||||||
|
|
||||||
import net.simon987.npcplugin.Factory;
|
|
||||||
import net.simon987.npcplugin.NpcPlugin;
|
import net.simon987.npcplugin.NpcPlugin;
|
||||||
import net.simon987.npcplugin.RadioTower;
|
import net.simon987.npcplugin.Settlement;
|
||||||
import net.simon987.server.GameServer;
|
|
||||||
import net.simon987.server.event.GameEvent;
|
import net.simon987.server.event.GameEvent;
|
||||||
import net.simon987.server.event.GameEventListener;
|
import net.simon987.server.event.GameEventListener;
|
||||||
import net.simon987.server.event.WorldGenerationEvent;
|
import net.simon987.server.event.WorldGenerationEvent;
|
||||||
import net.simon987.server.game.World;
|
import net.simon987.server.game.world.World;
|
||||||
|
import net.simon987.server.game.world.WorldGenerationException;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class WorldCreationListener implements GameEventListener {
|
public class WorldCreationListener implements GameEventListener {
|
||||||
@ -18,10 +16,14 @@ public class WorldCreationListener implements GameEventListener {
|
|||||||
/**
|
/**
|
||||||
* Spawn rate. Higher = rarer: A factory will be spawn about every FACTORY_SPAWN_RATE generated Worlds
|
* Spawn rate. Higher = rarer: A factory will be spawn about every FACTORY_SPAWN_RATE generated Worlds
|
||||||
*/
|
*/
|
||||||
private static final int FACTORY_SPAWN_RATE = 35;
|
private static int FACTORY_SPAWN_RATE = 0;
|
||||||
|
|
||||||
private Random random = new Random();
|
private Random random = new Random();
|
||||||
|
|
||||||
|
public WorldCreationListener(int factorySpawnRate) {
|
||||||
|
FACTORY_SPAWN_RATE = factorySpawnRate;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class getListenedEventType() {
|
public Class getListenedEventType() {
|
||||||
return WorldGenerationEvent.class;
|
return WorldGenerationEvent.class;
|
||||||
@ -32,66 +34,14 @@ public class WorldCreationListener implements GameEventListener {
|
|||||||
|
|
||||||
if (random.nextInt(FACTORY_SPAWN_RATE) == 0) {
|
if (random.nextInt(FACTORY_SPAWN_RATE) == 0) {
|
||||||
|
|
||||||
World world = ((WorldGenerationEvent) event).getWorld();
|
World world = (World) event.getSource();
|
||||||
|
|
||||||
outerLoopFactory:
|
try {
|
||||||
for (int x = 2; x < 12; x++) {
|
Settlement settlement = new Settlement(world);
|
||||||
for (int y = 2; y < 12; y++) {
|
NpcPlugin.settlementMap.put(world.getId(), settlement);
|
||||||
|
} catch (WorldGenerationException e) {
|
||||||
if ((!world.isTileBlocked(x, y) && !world.isTileBlocked(x + 1, y) &&
|
LogManager.LOGGER.fine(String.format("Exception during settlement generation: %s.",
|
||||||
!world.isTileBlocked(x, y + 1) && !world.isTileBlocked(x + 1, y + 1))) {
|
e.getMessage()));
|
||||||
|
|
||||||
Factory factory = new Factory();
|
|
||||||
|
|
||||||
factory.setWorld(world);
|
|
||||||
factory.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
|
||||||
factory.setX(x);
|
|
||||||
factory.setY(y);
|
|
||||||
|
|
||||||
if (factory.getAdjacentTile() == null) {
|
|
||||||
//Factory has no non-blocked adjacent tiles
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
world.addObject(factory);
|
|
||||||
world.incUpdatable();
|
|
||||||
|
|
||||||
LogManager.LOGGER.info("Spawned Factory at (" + world.getX() + ", " + world.getY() +
|
|
||||||
") (" + x + ", " + y + ")");
|
|
||||||
break outerLoopFactory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Also spawn a radio tower in the same World
|
|
||||||
Point p = world.getRandomPassableTile();
|
|
||||||
if (p != null) {
|
|
||||||
while (p.x == 0 || p.x == World.WORLD_SIZE - 1 || p.y == World.WORLD_SIZE - 1 || p.y == 0) {
|
|
||||||
p = world.getRandomPassableTile();
|
|
||||||
|
|
||||||
if (p == null) {
|
|
||||||
//World is full
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioTower radioTower = new RadioTower();
|
|
||||||
|
|
||||||
radioTower.setWorld(world);
|
|
||||||
radioTower.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
|
||||||
radioTower.setX(p.x);
|
|
||||||
radioTower.setY(p.y);
|
|
||||||
|
|
||||||
if (radioTower.getAdjacentTile() != null) {
|
|
||||||
//Radio Tower has adjacent tiles
|
|
||||||
world.addObject(radioTower);
|
|
||||||
world.incUpdatable(); //In case the Factory couldn't be spawned.
|
|
||||||
|
|
||||||
NpcPlugin.getRadioTowers().add(radioTower);
|
|
||||||
|
|
||||||
LogManager.LOGGER.info("Spawned RadioTower at (" + world.getX() + ", " + world.getY() +
|
|
||||||
") (" + p.x + ", " + p.y + ")");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package net.simon987.npcplugin.world;
|
||||||
|
|
||||||
|
import net.simon987.server.game.world.Tile;
|
||||||
|
|
||||||
|
public class TileVaultFloor extends Tile {
|
||||||
|
|
||||||
|
public static final int ID = 4;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package net.simon987.npcplugin.world;
|
||||||
|
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
import net.simon987.server.game.world.Tile;
|
||||||
|
|
||||||
|
public class TileVaultWall extends Tile {
|
||||||
|
|
||||||
|
public static final int ID = 5;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean walk(GameObject object) {
|
||||||
|
return false; //always blocked
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBlocked() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"hardware": [
|
||||||
|
{
|
||||||
|
"type": "net.simon987.cubotplugin.CubotLeg",
|
||||||
|
"address": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.cubotplugin.CubotLaser",
|
||||||
|
"address": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.cubotplugin.CubotLidar",
|
||||||
|
"address": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.cubotplugin.CubotDrill",
|
||||||
|
"address": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.npcplugin.NpcInventory",
|
||||||
|
"item": null,
|
||||||
|
"address": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.mischwplugin.RandomNumberGenerator",
|
||||||
|
"address": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.mischwplugin.Clock",
|
||||||
|
"address": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.cubotplugin.CubotHologram",
|
||||||
|
"color": 0,
|
||||||
|
"value": 0,
|
||||||
|
"string": "",
|
||||||
|
"mode": 0,
|
||||||
|
"address": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.npcplugin.NpcBattery",
|
||||||
|
"energy": 60000,
|
||||||
|
"max_energy": 60000,
|
||||||
|
"address": 262
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.npcplugin.RadioReceiverHardware",
|
||||||
|
"cubot": {
|
||||||
|
"$oid": "5c1d43e40d3d2530aba636df"
|
||||||
|
},
|
||||||
|
"address": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.cubotplugin.CubotComPort",
|
||||||
|
"address": 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "net.simon987.cubotplugin.CubotCore",
|
||||||
|
"address": 14
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
classpath=net.simon987.npcplugin.NpcPlugin
|
classpath=net.simon987.npcplugin.NpcPlugin
|
||||||
name=NPC Plugin
|
name=NPC Plugin
|
||||||
version=1.0
|
version=1.1
|
||||||
|
depend=Cubot Plugin
|
@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="Spring" name="Spring">
|
||||||
|
<configuration />
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
@ -15,10 +20,39 @@
|
|||||||
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
|
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
||||||
<orderEntry type="module" module-name="Server" />
|
<orderEntry type="module" module-name="Server" />
|
||||||
<orderEntry type="library" name="Maven: org.java-websocket:Java-WebSocket:1.3.6" level="project" />
|
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.6" level="project" />
|
||||||
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.42" level="project" />
|
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-sync:3.9.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:bson:3.9.1" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:2.10.1" level="project" />
|
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-core:3.9.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.1.5.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.1.6.RELEASE" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.sparkjava:spark-core:2.8.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-server:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-webapp:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-servlet:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-security:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-server:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-servlet:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.12.v20180830" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.sparkjava:spark-template-velocity:2.7.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.apache.velocity:velocity:1.7" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.4" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.25" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
@ -4,17 +4,15 @@
|
|||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>net.simon987.server</groupId>
|
<groupId>net.simon987.server</groupId>
|
||||||
<artifactId>server_root</artifactId>
|
<artifactId>server_root</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.simon987.pluginplant</groupId>
|
<groupId>net.simon987.pluginplant</groupId>
|
||||||
<artifactId>plugin-biomassBlob</artifactId>
|
<artifactId>plugin-biomassBlob</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -26,7 +24,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.simon987.server</groupId>
|
<groupId>net.simon987.server</groupId>
|
||||||
<artifactId>server</artifactId>
|
<artifactId>server</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
@ -1,26 +1,28 @@
|
|||||||
package net.simon987.biomassplugin;
|
package net.simon987.biomassplugin;
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import net.simon987.server.game.item.Item;
|
||||||
import com.mongodb.DBObject;
|
import net.simon987.server.game.objects.GameObject;
|
||||||
import net.simon987.server.game.GameObject;
|
import net.simon987.server.game.objects.InventoryHolder;
|
||||||
import net.simon987.server.game.InventoryHolder;
|
import org.bson.Document;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
public class BiomassBlob extends GameObject implements InventoryHolder {
|
public class BiomassBlob extends GameObject implements InventoryHolder {
|
||||||
|
|
||||||
private static final char MAP_INFO = 0x4000;
|
private static final char MAP_INFO = 0x0101;
|
||||||
public static final int ID = 2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Yield of the blob, in biomass units
|
* Yield of the blob, in biomass units
|
||||||
*/
|
*/
|
||||||
private int biomassCount;
|
private int biomassCount;
|
||||||
/**
|
|
||||||
* Style of the blob (Only visual)
|
|
||||||
*/
|
|
||||||
// private int style;
|
|
||||||
|
|
||||||
private static final int ITM_BIOMASS = 1;
|
public BiomassBlob() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public BiomassBlob(Document document) {
|
||||||
|
super(document);
|
||||||
|
|
||||||
|
biomassCount = document.getInteger("biomassCount");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char getMapInfo() {
|
public char getMapInfo() {
|
||||||
@ -28,30 +30,21 @@ public class BiomassBlob extends GameObject implements InventoryHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject serialise() {
|
public JSONObject jsonSerialise() {
|
||||||
|
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = super.jsonSerialise();
|
||||||
|
|
||||||
json.put("t", ID);
|
|
||||||
json.put("i", getObjectId());
|
|
||||||
json.put("x", getX());
|
|
||||||
json.put("y", getY());
|
|
||||||
json.put("b", biomassCount);
|
json.put("b", biomassCount);
|
||||||
// json.put("style", style);
|
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public Document mongoSerialise() {
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
Document dbObject = super.mongoSerialise();
|
||||||
|
|
||||||
dbObject.put("t", ID);
|
dbObject.put("biomassCount", biomassCount);
|
||||||
dbObject.put("i", getObjectId());
|
|
||||||
dbObject.put("x", getX());
|
|
||||||
dbObject.put("y", getY());
|
|
||||||
dbObject.put("b", biomassCount);
|
|
||||||
|
|
||||||
return dbObject;
|
return dbObject;
|
||||||
|
|
||||||
@ -65,55 +58,31 @@ public class BiomassBlob extends GameObject implements InventoryHolder {
|
|||||||
this.biomassCount = biomassCount;
|
this.biomassCount = biomassCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public int getStyle() {
|
|
||||||
// return style;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void setStyle(int style) {
|
|
||||||
// this.style = style;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public static BiomassBlob deserialize(DBObject obj) {
|
|
||||||
|
|
||||||
BiomassBlob biomassBlob = new BiomassBlob();
|
|
||||||
|
|
||||||
biomassBlob.setObjectId((long) obj.get("i"));
|
|
||||||
biomassBlob.setX((int) obj.get("x"));
|
|
||||||
biomassBlob.setY((int) obj.get("y"));
|
|
||||||
// biomassBlob.style = (int) json.get("style");
|
|
||||||
biomassBlob.biomassCount = (int) obj.get("b");
|
|
||||||
|
|
||||||
return biomassBlob;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an object attempts to place an item in this BiomassBlob
|
* Called when an object attempts to place an item in this BiomassBlob
|
||||||
*
|
*
|
||||||
* @param item item id (see MarConstants.ITEM_*)
|
|
||||||
* @return Always returns false
|
* @return Always returns false
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean placeItem(int item) {
|
public boolean placeItem(Item item) {
|
||||||
//Why would you want to place an item in a blob?
|
//Why would you want to place an item in a blob?
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canTakeItem(int item) {
|
public boolean canTakeItem(int itemId) {
|
||||||
return item == ITM_BIOMASS && biomassCount >= 1;
|
return itemId == ItemBiomass.ID && biomassCount >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an object attempts to take an item from this BiomassBlob.
|
* Called when an object attempts to take an item from this BiomassBlob.
|
||||||
* If the object requests biomass, it will be subtracted from biomassCount, and
|
* If the object requests biomass, it will be subtracted from biomassCount, and
|
||||||
* if it reaches 0, the plant is deleted
|
* if it reaches 0, the plant is deleted
|
||||||
*
|
|
||||||
* @param item item id (see MarConstants.ITEM_*)
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void takeItem(int item) {
|
public void takeItem(int itemId) {
|
||||||
|
|
||||||
if (item == ITM_BIOMASS) {
|
if (itemId == ItemBiomass.ID) {
|
||||||
if (biomassCount > 1) {
|
if (biomassCount > 1) {
|
||||||
biomassCount--;
|
biomassCount--;
|
||||||
} else {
|
} else {
|
||||||
@ -121,6 +90,5 @@ public class BiomassBlob extends GameObject implements InventoryHolder {
|
|||||||
setDead(true);
|
setDead(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,31 @@
|
|||||||
package net.simon987.biomassplugin;
|
package net.simon987.biomassplugin;
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.biomassplugin.event.ObjectDeathListener;
|
import net.simon987.biomassplugin.event.ObjectDeathListener;
|
||||||
import net.simon987.biomassplugin.event.WorldCreationListener;
|
import net.simon987.biomassplugin.event.WorldCreationListener;
|
||||||
import net.simon987.biomassplugin.event.WorldUpdateListener;
|
import net.simon987.biomassplugin.event.WorldUpdateListener;
|
||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.game.GameObject;
|
import net.simon987.server.IServerConfiguration;
|
||||||
import net.simon987.server.io.GameObjectDeserializer;
|
import net.simon987.server.game.objects.GameRegistry;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import net.simon987.server.plugin.ServerPlugin;
|
import net.simon987.server.plugin.ServerPlugin;
|
||||||
|
|
||||||
public class BiomassPlugin extends ServerPlugin implements GameObjectDeserializer {
|
|
||||||
|
public class BiomassPlugin extends ServerPlugin {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServerConfiguration config) {
|
public void init(GameServer gameServer) {
|
||||||
|
|
||||||
|
IServerConfiguration config = gameServer.getConfig();
|
||||||
|
GameRegistry registry = gameServer.getRegistry();
|
||||||
|
|
||||||
listeners.add(new WorldCreationListener());
|
listeners.add(new WorldCreationListener());
|
||||||
listeners.add(new WorldUpdateListener(config));
|
listeners.add(new WorldUpdateListener(config));
|
||||||
listeners.add(new ObjectDeathListener(config));
|
listeners.add(new ObjectDeathListener(config));
|
||||||
|
|
||||||
LogManager.LOGGER.info("Initialised Biomass plugin");
|
registry.registerGameObject(BiomassBlob.class);
|
||||||
}
|
registry.registerItem(ItemBiomass.ID, ItemBiomass.class);
|
||||||
|
|
||||||
@Override
|
LogManager.LOGGER.info("(BiomassPlugin) Initialised Biomass plugin");
|
||||||
public GameObject deserializeObject(DBObject object) {
|
|
||||||
|
|
||||||
int objType = (int) object.get("t");
|
|
||||||
|
|
||||||
if (objType == BiomassBlob.ID) {
|
|
||||||
|
|
||||||
return BiomassBlob.deserialize(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package net.simon987.biomassplugin;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.game.item.Item;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import net.simon987.server.game.objects.Rechargeable;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
public class ItemBiomass extends Item {
|
||||||
|
|
||||||
|
public static final int ID = 0x0001;
|
||||||
|
|
||||||
|
private static final int energy = GameServer.INSTANCE.getConfig().getInt("biomassEnergyValue");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBiomass() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBiomass(Document document) {
|
||||||
|
super(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear(ControllableUnit unit) {
|
||||||
|
if (unit instanceof Rechargeable) {
|
||||||
|
((Rechargeable) unit).storeEnergy(energy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char poll() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
package net.simon987.biomassplugin;
|
package net.simon987.biomassplugin;
|
||||||
|
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.game.world.TileMap;
|
||||||
import net.simon987.server.game.World;
|
import net.simon987.server.game.world.TilePlain;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.game.world.World;
|
||||||
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -21,12 +22,12 @@ public class WorldUtils {
|
|||||||
|
|
||||||
//Count number of plain tiles. If there is less plain tiles than desired amount of blobs,
|
//Count number of plain tiles. If there is less plain tiles than desired amount of blobs,
|
||||||
//set the desired amount of blobs to the plain tile count
|
//set the desired amount of blobs to the plain tile count
|
||||||
int[][] tiles = world.getTileMap().getTiles();
|
TileMap m = world.getTileMap();
|
||||||
int plainCount = 0;
|
int plainCount = 0;
|
||||||
for (int y = 0; y < World.WORLD_SIZE; y++) {
|
for (int y = 0; y < world.getWorldSize(); y++) {
|
||||||
for (int x = 0; x < World.WORLD_SIZE; x++) {
|
for (int x = 0; x < world.getWorldSize(); x++) {
|
||||||
|
|
||||||
if (tiles[x][y] == 0) {
|
if (m.getTileIdAt(x, y) == TilePlain.ID) {
|
||||||
plainCount++;
|
plainCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,14 +40,14 @@ public class WorldUtils {
|
|||||||
outerLoop:
|
outerLoop:
|
||||||
for (int i = 0; i < blobCount; i++) {
|
for (int i = 0; i < blobCount; i++) {
|
||||||
|
|
||||||
Point p = world.getTileMap().getRandomPlainTile();
|
Point p = m.getRandomTile(TilePlain.ID);
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
|
|
||||||
//Don't block worlds
|
//Don't block worlds
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
while (p.x == 0 || p.y == 0 || p.x == World.WORLD_SIZE - 1 || p.y == World.WORLD_SIZE - 1 ||
|
while (p.x == 0 || p.y == 0 || p.x == world.getWorldSize() - 1 || p.y == world.getWorldSize() - 1 ||
|
||||||
world.getGameObjectsAt(p.x, p.y).size() != 0) {
|
world.getGameObjectsAt(p.x, p.y).size() != 0) {
|
||||||
p = world.getTileMap().getRandomPlainTile();
|
p = m.getRandomTile(TilePlain.ID);
|
||||||
counter++;
|
counter++;
|
||||||
|
|
||||||
if (counter > 25) {
|
if (counter > 25) {
|
||||||
@ -62,8 +63,7 @@ public class WorldUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BiomassBlob biomassBlob = new BiomassBlob();
|
BiomassBlob biomassBlob = new BiomassBlob();
|
||||||
biomassBlob.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
biomassBlob.setObjectId(new ObjectId());
|
||||||
// biomassBlob.setStyle(0); //TODO: set style depending on difficulty level? or random? from config?
|
|
||||||
biomassBlob.setBiomassCount(yield);
|
biomassBlob.setBiomassCount(yield);
|
||||||
biomassBlob.setX(p.x);
|
biomassBlob.setX(p.x);
|
||||||
biomassBlob.setY(p.y);
|
biomassBlob.setY(p.y);
|
||||||
@ -73,9 +73,6 @@ public class WorldUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogManager.LOGGER.info("Generated " + biomassBlobs.size() + " biomassBlobs for World (" + world.getX() + ',' +
|
|
||||||
world.getY() + ')');
|
|
||||||
|
|
||||||
return biomassBlobs;
|
return biomassBlobs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
package net.simon987.biomassplugin.event;
|
package net.simon987.biomassplugin.event;
|
||||||
|
|
||||||
import net.simon987.biomassplugin.BiomassBlob;
|
import net.simon987.biomassplugin.BiomassBlob;
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.IServerConfiguration;
|
||||||
import net.simon987.server.ServerConfiguration;
|
|
||||||
import net.simon987.server.event.GameEvent;
|
import net.simon987.server.event.GameEvent;
|
||||||
import net.simon987.server.event.GameEventListener;
|
import net.simon987.server.event.GameEventListener;
|
||||||
import net.simon987.server.event.ObjectDeathEvent;
|
import net.simon987.server.event.ObjectDeathEvent;
|
||||||
import net.simon987.server.game.GameObject;
|
import net.simon987.server.game.objects.GameObject;
|
||||||
import net.simon987.server.game.World;
|
import net.simon987.server.game.world.World;
|
||||||
import net.simon987.server.logging.LogManager;
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles ObjectDeathEvent events
|
* Handles ObjectDeathEvent events
|
||||||
@ -17,9 +16,8 @@ public class ObjectDeathListener implements GameEventListener {
|
|||||||
|
|
||||||
private int biomassDropCount;
|
private int biomassDropCount;
|
||||||
|
|
||||||
public ObjectDeathListener(ServerConfiguration config) {
|
public ObjectDeathListener(IServerConfiguration config) {
|
||||||
biomassDropCount = config.getInt("harvester_biomass_drop_count");
|
biomassDropCount = config.getInt("harvester_biomass_drop_count");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -29,22 +27,19 @@ public class ObjectDeathListener implements GameEventListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(GameEvent event) {
|
public void handle(GameEvent event) {
|
||||||
// TODO: setup enum with all GameObject type IDs
|
|
||||||
if (((ObjectDeathEvent) event).getSourceObjectId() == 10) {
|
if (event.getSource().getClass().getCanonicalName().equals("net.simon987.npcplugin.HarvesterNPC")) {
|
||||||
//An HarvesterNPC ObjectDeathEvent is received
|
//An HarvesterNPC ObjectDeathEvent is received
|
||||||
GameObject dyingHarvesterNPC = (GameObject)event.getSource();
|
GameObject dyingHarvesterNPC = (GameObject)event.getSource();
|
||||||
|
|
||||||
|
|
||||||
//Don't spawn biomass on World border
|
//Don't spawn biomass on World border
|
||||||
if (dyingHarvesterNPC.getX() != 0 && dyingHarvesterNPC.getX() != World.WORLD_SIZE - 1 &&
|
if (dyingHarvesterNPC.getX() != 0 && dyingHarvesterNPC.getX() != dyingHarvesterNPC.getWorld().getWorldSize() - 1 &&
|
||||||
dyingHarvesterNPC.getY() != 0 && dyingHarvesterNPC.getY() != World.WORLD_SIZE - 1) {
|
dyingHarvesterNPC.getY() != 0 && dyingHarvesterNPC.getY() != dyingHarvesterNPC.getWorld().getWorldSize() - 1) {
|
||||||
//Create a new biomass
|
//Create a new biomass
|
||||||
BiomassBlob newBiomassBlob = createBiomassBlobAt(
|
BiomassBlob newBiomassBlob = createBiomassBlobAt(
|
||||||
dyingHarvesterNPC.getX(), dyingHarvesterNPC.getY(), dyingHarvesterNPC.getWorld());
|
dyingHarvesterNPC.getX(), dyingHarvesterNPC.getY(), dyingHarvesterNPC.getWorld());
|
||||||
//Add it to the world game objects
|
//Add it to the world game objects
|
||||||
dyingHarvesterNPC.getWorld().addObject(newBiomassBlob);
|
dyingHarvesterNPC.getWorld().addObject(newBiomassBlob);
|
||||||
LogManager.LOGGER.fine("Spawned biomass at (" + newBiomassBlob.getX() +
|
|
||||||
", " + newBiomassBlob.getY() + ")");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,8 +54,7 @@ public class ObjectDeathListener implements GameEventListener {
|
|||||||
private BiomassBlob createBiomassBlobAt(int x, int y, World world) {
|
private BiomassBlob createBiomassBlobAt(int x, int y, World world) {
|
||||||
|
|
||||||
BiomassBlob biomassBlob = new BiomassBlob();
|
BiomassBlob biomassBlob = new BiomassBlob();
|
||||||
biomassBlob.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
biomassBlob.setObjectId(new ObjectId());
|
||||||
// biomassBlob.setStyle(0); //TODO: set style depending on difficulty level? or random? from config?
|
|
||||||
biomassBlob.setBiomassCount(biomassDropCount);
|
biomassBlob.setBiomassCount(biomassDropCount);
|
||||||
biomassBlob.setX(x);
|
biomassBlob.setX(x);
|
||||||
biomassBlob.setY(y);
|
biomassBlob.setY(y);
|
||||||
|
@ -3,11 +3,11 @@ package net.simon987.biomassplugin.event;
|
|||||||
import net.simon987.biomassplugin.BiomassBlob;
|
import net.simon987.biomassplugin.BiomassBlob;
|
||||||
import net.simon987.biomassplugin.WorldUtils;
|
import net.simon987.biomassplugin.WorldUtils;
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.server.IServerConfiguration;
|
||||||
import net.simon987.server.event.GameEvent;
|
import net.simon987.server.event.GameEvent;
|
||||||
import net.simon987.server.event.GameEventListener;
|
import net.simon987.server.event.GameEventListener;
|
||||||
import net.simon987.server.event.WorldUpdateEvent;
|
import net.simon987.server.event.WorldUpdateEvent;
|
||||||
import net.simon987.server.game.World;
|
import net.simon987.server.game.world.World;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -23,7 +23,7 @@ public class WorldUpdateListener implements GameEventListener {
|
|||||||
private static int waitTime;
|
private static int waitTime;
|
||||||
private static int blobThreshold;
|
private static int blobThreshold;
|
||||||
|
|
||||||
public WorldUpdateListener(ServerConfiguration config) {
|
public WorldUpdateListener(IServerConfiguration config) {
|
||||||
|
|
||||||
minBlobCount = config.getInt("minBiomassRespawnCount");
|
minBlobCount = config.getInt("minBiomassRespawnCount");
|
||||||
maxBlobCount = config.getInt("maxBiomassRespawnCount");
|
maxBlobCount = config.getInt("maxBiomassRespawnCount");
|
||||||
@ -44,31 +44,32 @@ public class WorldUpdateListener implements GameEventListener {
|
|||||||
|
|
||||||
World world = ((WorldUpdateEvent) event).getWorld();
|
World world = ((WorldUpdateEvent) event).getWorld();
|
||||||
|
|
||||||
//If there is less than the respawn threshold,
|
if (world.getDimension().startsWith("w")) {
|
||||||
if (world.findObjects(BiomassBlob.class).size() < blobThreshold) {
|
//If there is less than the respawn threshold,
|
||||||
|
if (world.findObjects(BiomassBlob.class).size() < blobThreshold) {
|
||||||
|
|
||||||
//Set a timer for respawn_time ticks
|
//Set a timer for respawn_time ticks
|
||||||
if (!worldWaitMap.containsKey(world) || worldWaitMap.get(world) == 0L) {
|
if (!worldWaitMap.containsKey(world) || worldWaitMap.get(world) == 0L) {
|
||||||
worldWaitMap.put(world, GameServer.INSTANCE.getGameUniverse().getTime() + waitTime);
|
worldWaitMap.put(world, GameServer.INSTANCE.getGameUniverse().getTime() + waitTime);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
long waitUntil = worldWaitMap.get(world);
|
long waitUntil = worldWaitMap.get(world);
|
||||||
|
|
||||||
if (GameServer.INSTANCE.getGameUniverse().getTime() >= waitUntil) {
|
if (GameServer.INSTANCE.getGameUniverse().getTime() >= waitUntil) {
|
||||||
|
|
||||||
//If the timer was set less than respawn_time ticks ago, respawn the blobs
|
//If the timer was set less than respawn_time ticks ago, respawn the blobs
|
||||||
ArrayList<BiomassBlob> newBlobs = WorldUtils.generateBlobs(world, minBlobCount,
|
ArrayList<BiomassBlob> newBlobs = WorldUtils.generateBlobs(world, minBlobCount,
|
||||||
maxBlobCount, blobYield);
|
maxBlobCount, blobYield);
|
||||||
for (BiomassBlob blob : newBlobs) {
|
for (BiomassBlob blob : newBlobs) {
|
||||||
world.addObject(blob);
|
world.addObject(blob);
|
||||||
|
world.incUpdatable();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set the 'waitUntil' time to 0 to indicate that we are not waiting
|
||||||
|
worldWaitMap.replace(world, 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set the 'waitUntil' time to 0 to indicate that we are not waiting
|
|
||||||
worldWaitMap.replace(world, 0L);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,4 @@
|
|||||||
classpath=net.simon987.biomassplugin.BiomassPlugin
|
classpath=net.simon987.biomassplugin.BiomassPlugin
|
||||||
name=Biomass Plugin
|
name=Biomass Plugin
|
||||||
version=1.0
|
version=1.0
|
||||||
|
depend=NPC Plugin
|
31
Plugin Radioactive Cloud/pom.xml
Normal file
31
Plugin Radioactive Cloud/pom.xml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>net.simon987.server</groupId>
|
||||||
|
<artifactId>server_root</artifactId>
|
||||||
|
<version>1.4a</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>net.simon987.pluginradioactivecloud</groupId>
|
||||||
|
<artifactId>plugin-radioactiveCloud</artifactId>
|
||||||
|
<version>1.4a</version>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.json-simple</groupId>
|
||||||
|
<artifactId>json-simple</artifactId>
|
||||||
|
<version>1.1.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.simon987.server</groupId>
|
||||||
|
<artifactId>server</artifactId>
|
||||||
|
<version>1.4a</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1,32 @@
|
|||||||
|
package net.simon987.pluginradioactivecloud;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import net.simon987.server.game.objects.Enterable;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
import net.simon987.server.game.objects.Radioactive;
|
||||||
|
|
||||||
|
public class RadioactiveCloud extends GameObject implements Radioactive, Enterable {
|
||||||
|
private final static int CORRUPTION_BLOCK_SIZE =
|
||||||
|
GameServer.INSTANCE.getConfig().getInt("radioactive_cloud_corruption_block_size");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an object attempts to walk directly into a Enterable object
|
||||||
|
*
|
||||||
|
* @param object The game object that attempted to enter
|
||||||
|
* @return true if successful, false to block the object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean enter(GameObject object) {
|
||||||
|
if (object instanceof ControllableUnit) {
|
||||||
|
((ControllableUnit) object).getCpu().getMemory().corrupt(CORRUPTION_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getMapInfo() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package net.simon987.pluginradioactivecloud;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.logging.LogManager;
|
||||||
|
import net.simon987.server.plugin.ServerPlugin;
|
||||||
|
|
||||||
|
public class RadioactiveCloudPlugin extends ServerPlugin {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(GameServer gameServer) {
|
||||||
|
|
||||||
|
LogManager.LOGGER.info("(Radioactive cloud Plugin) Initialised Radioactive cloud plugin.");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package net.simon987.pluginradioactivecloud;
|
||||||
|
|
||||||
|
import net.simon987.server.GameServer;
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import net.simon987.server.game.objects.Enterable;
|
||||||
|
import net.simon987.server.game.objects.GameObject;
|
||||||
|
import net.simon987.server.game.objects.Radioactive;
|
||||||
|
|
||||||
|
public class RadioactiveObstacle extends GameObject implements Radioactive, Enterable {
|
||||||
|
|
||||||
|
private final static int corruptionBlockSize = GameServer.INSTANCE.getConfig().getInt("radioactive_obstacle_corruption_block_size");
|
||||||
|
private final static int MAP_INFO = 0x0A01; //10
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getMapInfo() {
|
||||||
|
return MAP_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean enter(GameObject object) {
|
||||||
|
if (object instanceof ControllableUnit) {
|
||||||
|
((ControllableUnit) object).getCpu().getMemory().corrupt(corruptionBlockSize);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
classpath=net.simon987.pluginradioactivecloud.RadioactiveCloudPlugin
|
||||||
|
name=Radioactive cloud Plugin
|
||||||
|
version=1.4
|
134
README.md
134
README.md
@ -1,26 +1,40 @@
|
|||||||
# [Live demo](https://muchassemblyrequired.com)
|
# Much-Assembly-Required
|
||||||
Program the 8086-like microprocessor of a robot in a grid-based multiplayer world. The game is web based so no installation is required.
|
|
||||||
In its current state, players can walk around the game universe and collect Biomass blobs & Iron/copper ore using the online code editor.
|
[](https://www.codefactor.io/repository/github/simon987/much-assembly-required)
|
||||||
|
[](https://ci.simon987.net/job/Much-Assembly-Required/)
|
||||||
|
|
||||||
|
**Much Assembly Required** allows you to program the 8086-like microprocessor of a robot in a grid-based multiplayer world. The game is web based so no installation is required. In its current state, players can walk around the game universe and collect Biomass blobs and Iron/copper ore using the online code editor.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Wiki: [GitHub](https://github.com/simon987/Much-Assembly-Required/wiki)
|
Wiki: [GitHub](https://github.com/simon987/Much-Assembly-Required/wiki)
|
||||||
Chat: [Slack](https://join.slack.com/t/muchassemblyrequired/shared_invite/enQtMjY3Mjc1OTUwNjEwLTkyOTIwOTA5OGY4MDVlMGI4NzM5YzlhMWJiMGY1OWE2NjUxODQ1NWQ1YTcxMTA1NGZkYzNjYzMyM2E1ODdmNzg)
|
Chat: [Slack](https://join.slack.com/t/muchassemblyrequired/shared_invite/enQtMjY3Mjc1OTUwNjEwLWRjMjRkZTg2N2EyNWRjN2YyMDc0YzIyMTUyYzFiNTBmMTU3OGQ1ZjA0MWY0M2IyYjUxZTA4NjRkMWVkNDk2NzY)
|
||||||
|
|
||||||
## VS Code Extensions
|
|
||||||
- [Much Assembly Required (Upload on Save)](https://marketplace.visualstudio.com/items?itemName=tomhodder.much-assembly-required-upload-on-save) by tomhodder
|
|
||||||
- [Much Assembly Required Language Support](https://marketplace.visualstudio.com/items?itemName=PJB3005.much-assembly-required-language-support) by PJB3005
|
|
||||||
|
|
||||||
# Deploying the server
|
# Deploying the server
|
||||||
|
|
||||||
Note: You can find the frontend [here](https://github.com/simon987/Much-Assembly-Required-Frontend)
|
## Linux
|
||||||
|
|
||||||
|
**Installing tools**
|
||||||
|
|
||||||
## Linux (Ubuntu 16.04)
|
On Ubuntu 16.04:
|
||||||
```bash
|
```bash
|
||||||
# Install tools
|
sudo apt install git maven openjdk-8-jdk mongodb
|
||||||
sudo apt install git maven openjdk-8-jdk
|
```
|
||||||
|
|
||||||
|
On Arch:
|
||||||
|
``` bash
|
||||||
|
sudo pacman -S git maven jdk8-opendjk
|
||||||
|
yay -S mongodb-bin
|
||||||
|
|
||||||
|
# Don't forget to start mongodb
|
||||||
|
sudo systemctl start mongodb.service
|
||||||
|
```
|
||||||
|
|
||||||
|
*If needed, visit [yay installation](https://github.com/Jguer/yay#installation) and [troubleshooting mongodb](https://wiki.archlinux.org/index.php/MongoDB#Troubleshooting).*
|
||||||
|
|
||||||
|
**Deploying server**
|
||||||
|
|
||||||
|
``` bash
|
||||||
# Obtain source files
|
# Obtain source files
|
||||||
git clone https://github.com/simon987/Much-Assembly-Required.git
|
git clone https://github.com/simon987/Much-Assembly-Required.git
|
||||||
|
|
||||||
@ -30,19 +44,19 @@ mvn package
|
|||||||
|
|
||||||
# Run
|
# Run
|
||||||
cd target
|
cd target
|
||||||
java -jar server-1.2a.jar
|
java -jar server-1.4a.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
## Windows (tested on Windows 10)
|
## Windows (tested on Windows 10)
|
||||||
|
|
||||||
Installation instructions:
|
Installation instructions:
|
||||||
1. Download the JDK from [here](http://www.oracle.com/technetwork/java/javase/downloads/index.html).
|
1. Download the JDK from [here](http://www.oracle.com/technetwork/java/javase/downloads/index.html).
|
||||||
Install the JDK and update your PATH and JAVA_HOME enviroment variables.
|
Install the JDK and update your PATH and JAVA_HOME environment variables.
|
||||||
2. Download Maven from [here](https://maven.apache.org/).
|
2. Download Maven from [here](https://maven.apache.org/).
|
||||||
Install Maven (following the README) and update your PATH enviroment variable.
|
Install Maven (following the README) and update your PATH environment variable.
|
||||||
3. Download Mongo DB Community from [here](https://www.mongodb.com/download-center#community).
|
3. Download Mongo DB Community from [here](https://www.mongodb.com/download-center#community).
|
||||||
Install Mongo DB following the instructions [here](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/).
|
Install Mongo DB following the instructions [here](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/).
|
||||||
Update your PATH enviroment variable.
|
Update your PATH environment variable.
|
||||||
|
|
||||||
Building instructions:
|
Building instructions:
|
||||||
```batch
|
```batch
|
||||||
@ -61,10 +75,69 @@ mongod
|
|||||||
```batch
|
```batch
|
||||||
:: Runs the MAR server
|
:: Runs the MAR server
|
||||||
cd Much-Assembly-Required\target
|
cd Much-Assembly-Required\target
|
||||||
java -jar server-1.2a.jar
|
java -jar server-1.4a.jar
|
||||||
```
|
```
|
||||||
3. Run the frontend, following the instructions that you can find [here](https://github.com/simon987/Much-Assembly-Required-Frontend).
|
|
||||||
|
|
||||||
|
## macOS (tested on Sierra 10.12.6)
|
||||||
|
|
||||||
|
**Installation**
|
||||||
|
|
||||||
|
1. Install [Maven3](https://maven.apache.org/)
|
||||||
|
-Add Maven bin to your path
|
||||||
|
```bash
|
||||||
|
export PATH=/path/to/maven/bin.:$PATH
|
||||||
|
```
|
||||||
|
2. Install [MongoDB](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/?_ga=2.201359831.774868398.1539369140-197602459.1539369140).
|
||||||
|
-Via Brew:
|
||||||
|
```bash
|
||||||
|
#Update brew
|
||||||
|
brew update
|
||||||
|
|
||||||
|
#Install mongodb
|
||||||
|
brew install mongodb
|
||||||
|
|
||||||
|
#Install latest development release
|
||||||
|
brew install mongodb --devel
|
||||||
|
```
|
||||||
|
-Via .tar.gz
|
||||||
|
```bash
|
||||||
|
#Extract files:
|
||||||
|
tar -zxvf mongodb-osx-ssl-x86_64-4.0.3.tgz
|
||||||
|
|
||||||
|
#Ensure binaries are in your path
|
||||||
|
export PATH=<mongodb-install-directory>/bin:$PATH
|
||||||
|
```
|
||||||
|
If you do not wish to use the default data directory (/data/db), follow the steps for running MongoDB in the install doc.
|
||||||
|
|
||||||
|
**Deploying Server**
|
||||||
|
|
||||||
|
1. Begin MongoDB service
|
||||||
|
```bash
|
||||||
|
#If brew:
|
||||||
|
#Launch on login
|
||||||
|
brew services start mongodb
|
||||||
|
#Or, if you don't want/need a background service you can just run:
|
||||||
|
mongod --config /usr/local/etc/mongod.conf
|
||||||
|
|
||||||
|
#If binary:
|
||||||
|
mongod
|
||||||
|
#Optional, set data directory path:
|
||||||
|
mongod --dbpath <path to data directory>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Deploy server:
|
||||||
|
```bash
|
||||||
|
# Obtain source files
|
||||||
|
git clone https://github.com/simon987/Much-Assembly-Required.git
|
||||||
|
|
||||||
|
# Build
|
||||||
|
cd Much-Assembly-Required
|
||||||
|
mvn package
|
||||||
|
|
||||||
|
# Run
|
||||||
|
cd target
|
||||||
|
java -jar server-1.4a.jar
|
||||||
|
```
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
### Requirements
|
### Requirements
|
||||||
@ -79,8 +152,25 @@ application's directory:
|
|||||||
|
|
||||||
`docker-compose up`
|
`docker-compose up`
|
||||||
|
|
||||||
This will start MySQL and then build and run this application. It will
|
Make sure to change `mongo_address` in `config.properties` to `mongodb`.
|
||||||
be available via http://localhost.
|
|
||||||
|
|
||||||
Note that there is currently no frontend web application serving the
|
|
||||||
WebSocket feed served by the `Server` application!
|
## Vagrant
|
||||||
|
### Requirements
|
||||||
|
1. [Vagrant](https://www.vagrantup.com/downloads.html)
|
||||||
|
2. [VirtualBox](https://www.virtualbox.org/wiki/Downloads)
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
When vagrant is installed, you can build and start this application by running the following
|
||||||
|
command inside this application's directory:
|
||||||
|
|
||||||
|
`vagrant up`
|
||||||
|
|
||||||
|
# Running
|
||||||
|
|
||||||
|
Once the server is running, you should be able to connect to `http://localhost:4567` with your browser
|
||||||
|
|
||||||
|
## VS Code Extensions
|
||||||
|
- [Much Assembly Required (Upload on Save)](https://marketplace.visualstudio.com/items?itemName=tomhodder.much-assembly-required-upload-on-save) by tomhodder
|
||||||
|
- [Much Assembly Required Language Support](https://marketplace.visualstudio.com/items?itemName=PJB3005.much-assembly-required-language-support) by PJB3005
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
|
||||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" name="Maven: org.java-websocket:Java-WebSocket:1.3.6" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.42" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.2" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.mongodb:mongo-java-driver:2.10.1" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
@ -24,10 +24,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
<directory>../Server/src/main/resources</directory>
|
<directory>../Server/src/main/resources</directory>
|
||||||
<filtering>true</filtering>
|
|
||||||
<includes>
|
|
||||||
<include>config.properties</include>
|
|
||||||
</includes>
|
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
</configuration>
|
</configuration>
|
||||||
@ -81,6 +77,7 @@
|
|||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<version>2.7.2</version>
|
<version>2.7.2</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
<forkMode>never</forkMode>
|
||||||
<workingDirectory>./src/main/resources</workingDirectory>
|
<workingDirectory>./src/main/resources</workingDirectory>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
@ -89,25 +86,15 @@
|
|||||||
|
|
||||||
<groupId>net.simon987.server</groupId>
|
<groupId>net.simon987.server</groupId>
|
||||||
<artifactId>server</artifactId>
|
<artifactId>server</artifactId>
|
||||||
<version>1.2a</version>
|
<version>1.4a</version>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.java-websocket</groupId>
|
|
||||||
<artifactId>Java-WebSocket</artifactId>
|
|
||||||
<version>1.3.6</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.12</version>
|
<version>4.13.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>mysql</groupId>
|
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
|
||||||
<version>5.1.42</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.googlecode.json-simple</groupId>
|
<groupId>com.googlecode.json-simple</groupId>
|
||||||
<artifactId>json-simple</artifactId>
|
<artifactId>json-simple</artifactId>
|
||||||
@ -116,12 +103,33 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-text</artifactId>
|
<artifactId>commons-text</artifactId>
|
||||||
<version>1.2</version>
|
<version>1.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mongodb</groupId>
|
<groupId>org.mongodb</groupId>
|
||||||
<artifactId>mongo-java-driver</artifactId>
|
<artifactId>mongodb-driver-sync</artifactId>
|
||||||
<version>2.10.1</version>
|
<version>3.9.1</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-core</artifactId>
|
||||||
|
<version>5.1.11.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sparkjava</groupId>
|
||||||
|
<artifactId>spark-core</artifactId>
|
||||||
|
<version>2.8.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sparkjava</groupId>
|
||||||
|
<artifactId>spark-template-velocity</artifactId>
|
||||||
|
<version>2.7.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>1.7.25</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -1,21 +1,29 @@
|
|||||||
package net.simon987.server;
|
package net.simon987.server;
|
||||||
|
|
||||||
|
import com.mongodb.MongoClientException;
|
||||||
import com.mongodb.*;
|
import com.mongodb.client.*;
|
||||||
import net.simon987.server.assembly.exception.CancelledException;
|
import com.mongodb.client.model.ReplaceOptions;
|
||||||
|
import net.simon987.server.crypto.CryptoProvider;
|
||||||
|
import net.simon987.server.crypto.SecretKeyGenerator;
|
||||||
import net.simon987.server.event.GameEvent;
|
import net.simon987.server.event.GameEvent;
|
||||||
import net.simon987.server.event.GameEventDispatcher;
|
import net.simon987.server.event.GameEventDispatcher;
|
||||||
import net.simon987.server.event.TickEvent;
|
import net.simon987.server.event.TickEvent;
|
||||||
import net.simon987.server.game.DayNightCycle;
|
|
||||||
import net.simon987.server.game.GameUniverse;
|
import net.simon987.server.game.GameUniverse;
|
||||||
import net.simon987.server.game.World;
|
import net.simon987.server.game.debug.*;
|
||||||
|
import net.simon987.server.game.item.ItemCopper;
|
||||||
|
import net.simon987.server.game.item.ItemIron;
|
||||||
|
import net.simon987.server.game.objects.GameRegistry;
|
||||||
|
import net.simon987.server.game.world.*;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import net.simon987.server.plugin.PluginManager;
|
import net.simon987.server.plugin.PluginManager;
|
||||||
|
import net.simon987.server.plugin.ServerPlugin;
|
||||||
import net.simon987.server.user.User;
|
import net.simon987.server.user.User;
|
||||||
import net.simon987.server.webserver.SocketServer;
|
import net.simon987.server.user.UserManager;
|
||||||
|
import net.simon987.server.user.UserStatsHelper;
|
||||||
|
import net.simon987.server.websocket.SocketServer;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
import java.io.File;
|
import java.util.ArrayList;
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
public class GameServer implements Runnable {
|
public class GameServer implements Runnable {
|
||||||
|
|
||||||
@ -25,7 +33,7 @@ public class GameServer implements Runnable {
|
|||||||
private GameEventDispatcher eventDispatcher;
|
private GameEventDispatcher eventDispatcher;
|
||||||
private PluginManager pluginManager;
|
private PluginManager pluginManager;
|
||||||
|
|
||||||
private ServerConfiguration config;
|
private IServerConfiguration config;
|
||||||
|
|
||||||
private SocketServer socketServer;
|
private SocketServer socketServer;
|
||||||
|
|
||||||
@ -33,48 +41,80 @@ public class GameServer implements Runnable {
|
|||||||
|
|
||||||
private DayNightCycle dayNightCycle;
|
private DayNightCycle dayNightCycle;
|
||||||
|
|
||||||
private MongoClient mongo = null;
|
private CryptoProvider cryptoProvider;
|
||||||
|
|
||||||
|
private MongoClient mongo;
|
||||||
|
|
||||||
|
private UserManager userManager;
|
||||||
|
|
||||||
|
private UserStatsHelper userStatsHelper;
|
||||||
|
|
||||||
|
private GameRegistry gameRegistry;
|
||||||
|
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
public GameServer() {
|
public GameServer() {
|
||||||
|
|
||||||
this.config = new ServerConfiguration("config.properties");
|
this.config = new ServerConfiguration("config.properties");
|
||||||
|
|
||||||
try{
|
String connString = String.format("mongodb://%s:%d",
|
||||||
mongo = new MongoClient("localhost", 27017);
|
config.getString("mongo_address"), config.getInt("mongo_port"));
|
||||||
} catch (UnknownHostException e) {
|
mongo = MongoClients.create(connString);
|
||||||
e.printStackTrace();
|
MongoDatabase db = mongo.getDatabase(config.getString("mongo_dbname"));
|
||||||
}
|
|
||||||
|
MongoCollection<Document> userCollection = db.getCollection("user");
|
||||||
|
|
||||||
|
userManager = new UserManager(userCollection);
|
||||||
|
userStatsHelper = new UserStatsHelper(userCollection);
|
||||||
|
|
||||||
gameUniverse = new GameUniverse(config);
|
gameUniverse = new GameUniverse(config);
|
||||||
gameUniverse.setMongo(mongo);
|
gameUniverse.setMongo(mongo);
|
||||||
pluginManager = new PluginManager();
|
gameRegistry = new GameRegistry();
|
||||||
|
pluginManager = new PluginManager(this);
|
||||||
|
|
||||||
maxExecutionTime = config.getInt("user_timeout");
|
maxExecutionTime = config.getInt("user_timeout");
|
||||||
|
|
||||||
|
cryptoProvider = new CryptoProvider();
|
||||||
|
|
||||||
dayNightCycle = new DayNightCycle();
|
dayNightCycle = new DayNightCycle();
|
||||||
|
|
||||||
//Load all plugins in plugins folder, if it doesn't exist, create it
|
SecretKeyGenerator keyGenerator = new SecretKeyGenerator();
|
||||||
File pluginDir = new File("plugins/");
|
secretKey = config.getString("secret_key");
|
||||||
File[] pluginDirListing = pluginDir.listFiles();
|
if (secretKey == null) {
|
||||||
|
secretKey = keyGenerator.generate();
|
||||||
|
config.setString("secret_key", secretKey);
|
||||||
|
}
|
||||||
|
|
||||||
if (pluginDirListing != null) {
|
if (!pluginManager.loadInFolder("plugins/")) {
|
||||||
for (File pluginFile : pluginDirListing) {
|
System.exit(-1);
|
||||||
|
|
||||||
if (pluginFile.getName().endsWith(".jar")) {
|
|
||||||
pluginManager.load(pluginFile, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!pluginDir.mkdir()) {
|
|
||||||
LogManager.LOGGER.severe("Couldn't create plugin directory");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eventDispatcher = new GameEventDispatcher(pluginManager);
|
eventDispatcher = new GameEventDispatcher(pluginManager);
|
||||||
eventDispatcher.getListeners().add(dayNightCycle);
|
eventDispatcher.getListeners().add(dayNightCycle);
|
||||||
|
|
||||||
|
//Debug command Listeners
|
||||||
|
eventDispatcher.getListeners().add(new ComPortMsgCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new CreateWorldCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new KillAllCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new MoveObjCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new ObjInfoCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new SetTileAtCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new SpawnObjCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new TpObjectCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new UserInfoCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new HealObjCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new DamageObjCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new SetEnergyCommandListener());
|
||||||
|
eventDispatcher.getListeners().add(new SaveGameCommandListener());
|
||||||
|
|
||||||
|
gameRegistry.registerItem(ItemCopper.ID, ItemCopper.class);
|
||||||
|
gameRegistry.registerItem(ItemIron.ID, ItemIron.class);
|
||||||
|
|
||||||
|
gameRegistry.registerTile(TileVoid.ID, TileVoid.class);
|
||||||
|
gameRegistry.registerTile(TilePlain.ID, TilePlain.class);
|
||||||
|
gameRegistry.registerTile(TileWall.ID, TileWall.class);
|
||||||
|
gameRegistry.registerTile(TileCopper.ID, TileCopper.class);
|
||||||
|
gameRegistry.registerTile(TileIron.ID, TileIron.class);
|
||||||
|
gameRegistry.registerTile(TileFluid.ID, TileFluid.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameUniverse getGameUniverse() {
|
public GameUniverse getGameUniverse() {
|
||||||
@ -85,6 +125,10 @@ public class GameServer implements Runnable {
|
|||||||
return eventDispatcher;
|
return eventDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CryptoProvider getCryptoProvider() {
|
||||||
|
return cryptoProvider;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
LogManager.LOGGER.info("(G) Started game loop");
|
LogManager.LOGGER.info("(G) Started game loop");
|
||||||
@ -104,8 +148,6 @@ public class GameServer implements Runnable {
|
|||||||
uTime = System.currentTimeMillis() - startTime;
|
uTime = System.currentTimeMillis() - startTime;
|
||||||
waitTime = config.getInt("tick_length") - uTime;
|
waitTime = config.getInt("tick_length") - uTime;
|
||||||
|
|
||||||
LogManager.LOGGER.info("Wait time : " + waitTime + "ms | Update time: " + uTime + "ms | " + (int) (((double) uTime / waitTime) * 100) + "% load");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (waitTime >= 0) {
|
if (waitTime >= 0) {
|
||||||
Thread.sleep(waitTime);
|
Thread.sleep(waitTime);
|
||||||
@ -113,10 +155,7 @@ public class GameServer implements Runnable {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tick() {
|
private void tick() {
|
||||||
@ -126,33 +165,30 @@ public class GameServer implements Runnable {
|
|||||||
GameEvent event = new TickEvent(gameUniverse.getTime());
|
GameEvent event = new TickEvent(gameUniverse.getTime());
|
||||||
eventDispatcher.dispatch(event); //Ignore cancellation
|
eventDispatcher.dispatch(event); //Ignore cancellation
|
||||||
|
|
||||||
|
|
||||||
//Process user code
|
//Process user code
|
||||||
for (User user : gameUniverse.getUsers()) {
|
for (User user : gameUniverse.getUsers()) {
|
||||||
|
|
||||||
if (user.getCpu() != null) {
|
if (user.getControlledUnit() != null && user.getControlledUnit().getCpu() != null) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
int timeout = Math.min(user.getControlledUnit().getEnergy(), maxExecutionTime);
|
int timeout = Math.min(user.getControlledUnit().getEnergy(), maxExecutionTime);
|
||||||
|
|
||||||
user.getCpu().reset();
|
user.getControlledUnit().getCpu().reset();
|
||||||
int cost = user.getCpu().execute(timeout);
|
int cost = user.getControlledUnit().getCpu().execute(timeout);
|
||||||
user.getControlledUnit().spendEnergy(cost);
|
user.getControlledUnit().spendEnergy(cost);
|
||||||
|
user.addTime(cost);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogManager.LOGGER.severe("Error executing " + user.getUsername() + "'s code");
|
LogManager.LOGGER.severe("Error executing " + user.getUsername() + "'s code");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Process each worlds
|
//Process each worlds
|
||||||
int updatedWorlds = 0;
|
|
||||||
for (World world : gameUniverse.getWorlds()) {
|
for (World world : gameUniverse.getWorlds()) {
|
||||||
if (world.shouldUpdate()) {
|
if (world.shouldUpdate()) {
|
||||||
world.update();
|
world.update();
|
||||||
updatedWorlds++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,104 +198,120 @@ public class GameServer implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
socketServer.tick();
|
socketServer.tick();
|
||||||
|
|
||||||
LogManager.LOGGER.info("Processed " + gameUniverse.getWorldCount() + " worlds (" + updatedWorlds +
|
|
||||||
") updated");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void load() {
|
void load() {
|
||||||
|
|
||||||
LogManager.LOGGER.info("Loading all data from MongoDB");
|
LogManager.LOGGER.info("Loading all data from MongoDB");
|
||||||
|
|
||||||
DB db = mongo.getDB("mar");
|
MongoDatabase db = mongo.getDatabase(config.getString("mongo_dbname"));
|
||||||
|
|
||||||
DBCollection worlds = db.getCollection("world");
|
MongoCollection<Document> worlds = db.getCollection("world");
|
||||||
DBCollection users = db.getCollection("user");
|
MongoCollection<Document> server = db.getCollection("server");
|
||||||
DBCollection server = db.getCollection("server");
|
|
||||||
|
|
||||||
BasicDBObject whereQuery = new BasicDBObject();
|
Document whereQuery = new Document();
|
||||||
whereQuery.put("shouldUpdate", true);
|
whereQuery.put("shouldUpdate", true);
|
||||||
DBCursor cursor = worlds.find(whereQuery);
|
MongoCursor<Document> cursor = worlds.find(whereQuery).iterator();
|
||||||
GameUniverse universe = GameServer.INSTANCE.getGameUniverse();
|
GameUniverse universe = GameServer.INSTANCE.getGameUniverse();
|
||||||
while (cursor.hasNext()) {
|
while (cursor.hasNext()) {
|
||||||
World w = World.deserialize(cursor.next());
|
World w = World.deserialize(cursor.next());
|
||||||
universe.addWorld(w);
|
universe.addWorld(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load users
|
//Load users
|
||||||
cursor = users.find();
|
ArrayList<User> userList = userManager.getUsers();
|
||||||
while (cursor.hasNext()) {
|
for (User user : userList) {
|
||||||
try {
|
universe.addUser(user);
|
||||||
universe.addUser(User.deserialize(cursor.next()));
|
|
||||||
} catch (CancelledException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load misc server info
|
//Load server & plugin data
|
||||||
cursor = server.find();
|
cursor = server.find().iterator();
|
||||||
if (cursor.hasNext()) {
|
if (cursor.hasNext()) {
|
||||||
DBObject serverObj = cursor.next();
|
Document serverObj = cursor.next();
|
||||||
gameUniverse.setTime((long) serverObj.get("time"));
|
gameUniverse.setTime((long) serverObj.get("time"));
|
||||||
gameUniverse.setNextObjectId((long) serverObj.get("nextObjectId"));
|
|
||||||
|
Document plugins = (Document) serverObj.get("plugins");
|
||||||
|
|
||||||
|
for (String pluginName : plugins.keySet()) {
|
||||||
|
ServerPlugin plugin = pluginManager.getPluginByName(pluginName);
|
||||||
|
plugin.load((Document) plugins.get(pluginName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogManager.LOGGER.info("Done loading! W:" + GameServer.INSTANCE.getGameUniverse().getWorldCount() +
|
LogManager.LOGGER.info("Done loading! W:" + GameServer.INSTANCE.getGameUniverse().getWorldCount() +
|
||||||
" | U:" + GameServer.INSTANCE.getGameUniverse().getUserCount());
|
" | U:" + GameServer.INSTANCE.getGameUniverse().getUserCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void save() {
|
public void save() {
|
||||||
|
|
||||||
LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorldCount() + " | U:" + gameUniverse.getUserCount());
|
LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorldCount() + " | U:" + gameUniverse.getUserCount());
|
||||||
try{
|
|
||||||
DB db = mongo.getDB("mar");
|
|
||||||
|
|
||||||
int unloaded_worlds = 0;
|
ClientSession session = null;
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
session = mongo.startSession();
|
||||||
|
session.startTransaction();
|
||||||
|
} catch (MongoClientException e) {
|
||||||
|
LogManager.LOGGER.fine("Could not create mongoDB session, will not use transaction feature. " +
|
||||||
|
"(This message can be safely ignored)");
|
||||||
|
}
|
||||||
|
|
||||||
DBCollection worlds = db.getCollection("world");
|
MongoDatabase db = mongo.getDatabase(config.getString("mongo_dbname"));
|
||||||
DBCollection users = db.getCollection("user");
|
ReplaceOptions updateOptions = new ReplaceOptions();
|
||||||
DBCollection server = db.getCollection("server");
|
updateOptions.upsert(true);
|
||||||
|
|
||||||
int insertedWorlds = 0;
|
int unloaded_worlds = 0;
|
||||||
GameUniverse universe = GameServer.INSTANCE.getGameUniverse();
|
|
||||||
|
MongoCollection<Document> worlds = db.getCollection("world");
|
||||||
|
MongoCollection<Document> users = db.getCollection("user");
|
||||||
|
MongoCollection<Document> server = db.getCollection("server");
|
||||||
|
|
||||||
|
int insertedWorlds = 0;
|
||||||
|
GameUniverse universe = GameServer.INSTANCE.getGameUniverse();
|
||||||
for (World w : universe.getWorlds()) {
|
for (World w : universe.getWorlds()) {
|
||||||
// LogManager.LOGGER.fine("Saving world "+w.getId()+" to mongodb");
|
|
||||||
insertedWorlds++;
|
insertedWorlds++;
|
||||||
worlds.save(w.mongoSerialise());
|
worlds.replaceOne(new Document("_id", w.getId()), w.mongoSerialise(), updateOptions);
|
||||||
|
|
||||||
// If the world should unload, it is removed from the Universe after having been saved.
|
//If the world should unload, it is removed from the Universe after having been saved.
|
||||||
if (w.shouldUnload()){
|
if (w.shouldUnload()) {
|
||||||
unloaded_worlds++;
|
unloaded_worlds++;
|
||||||
// LogManager.LOGGER.fine("Unloading world "+w.getId()+" from universe");
|
|
||||||
universe.removeWorld(w);
|
universe.removeWorld(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (User u : GameServer.INSTANCE.getGameUniverse().getUsers()) {
|
for (User u : GameServer.INSTANCE.getGameUniverse().getUsers()) {
|
||||||
|
if (!u.isGuest()) {
|
||||||
|
users.replaceOne(new Document("_id", u.getUsername()), u.mongoSerialise(), updateOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!u.isGuest()) {
|
Document serverObj = new Document();
|
||||||
users.save(u.mongoSerialise());
|
serverObj.put("time", gameUniverse.getTime());
|
||||||
}
|
|
||||||
|
|
||||||
}
|
Document plugins = new Document();
|
||||||
|
for (ServerPlugin plugin : pluginManager.getPlugins()) {
|
||||||
|
plugins.put(plugin.getName(), plugin.mongoSerialise());
|
||||||
|
}
|
||||||
|
serverObj.put("plugins", plugins);
|
||||||
|
|
||||||
BasicDBObject serverObj = new BasicDBObject();
|
//A constant id ensures only one entry is kept and updated, instead of a new entry created every save.
|
||||||
serverObj.put("_id","serverinfo"); // a constant id ensures only one entry is kept and updated, instead of a new entry created every save.
|
server.replaceOne(new Document("_id", "serverinfo"), serverObj, updateOptions);
|
||||||
serverObj.put("time", gameUniverse.getTime());
|
if (session != null) {
|
||||||
serverObj.put("nextObjectId", gameUniverse.getNextObjectId());
|
session.commitTransaction();
|
||||||
server.save(serverObj);
|
}
|
||||||
|
|
||||||
LogManager.LOGGER.info(""+insertedWorlds+" worlds saved, "+unloaded_worlds+" unloaded");
|
LogManager.LOGGER.info("" + insertedWorlds + " worlds saved, " + unloaded_worlds + " unloaded");
|
||||||
LogManager.LOGGER.info("Done!");
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogManager.LOGGER.severe("Problem happened during save function");
|
LogManager.LOGGER.severe("Problem happened during save function");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
||||||
|
if (session != null) {
|
||||||
|
session.commitTransaction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerConfiguration getConfig() {
|
public IServerConfiguration getConfig() {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,4 +326,25 @@ public class GameServer implements Runnable {
|
|||||||
public DayNightCycle getDayNightCycle() {
|
public DayNightCycle getDayNightCycle() {
|
||||||
return dayNightCycle;
|
return dayNightCycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserManager getUserManager() {
|
||||||
|
return userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserStatsHelper getUserStatsHelper() {
|
||||||
|
return userStatsHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameRegistry getRegistry() {
|
||||||
|
return gameRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecretKey() {
|
||||||
|
return secretKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecretKey(String secretKey) {
|
||||||
|
this.secretKey = secretKey;
|
||||||
|
config.setString("secret_key", secretKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package net.simon987.server;
|
||||||
|
|
||||||
|
public interface IServerConfiguration {
|
||||||
|
|
||||||
|
int getInt(String key);
|
||||||
|
|
||||||
|
String getString(String key);
|
||||||
|
|
||||||
|
void setInt(String key, int value);
|
||||||
|
|
||||||
|
void setString(String key, String value);
|
||||||
|
}
|
@ -1,26 +1,25 @@
|
|||||||
package net.simon987.server;
|
package net.simon987.server;
|
||||||
|
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import net.simon987.server.webserver.SocketServer;
|
import net.simon987.server.web.WebServer;
|
||||||
|
import spark.Spark;
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
|
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
|
||||||
ServerConfiguration config = new ServerConfiguration("config.properties");
|
ServerConfiguration config = new ServerConfiguration("config.properties");
|
||||||
LogManager.initialize(config);
|
LogManager.initialize(config);
|
||||||
|
|
||||||
//Load
|
|
||||||
GameServer.INSTANCE.load();
|
GameServer.INSTANCE.load();
|
||||||
|
|
||||||
SocketServer socketServer = new SocketServer(new InetSocketAddress(config.getString("webSocket_host"),
|
//Web server
|
||||||
config.getInt("webSocket_port")), config);
|
WebServer webServer = new WebServer(GameServer.INSTANCE.getConfig());
|
||||||
|
|
||||||
GameServer.INSTANCE.setSocketServer(socketServer);
|
Spark.awaitInitialization();
|
||||||
|
GameServer.INSTANCE.setSocketServer(webServer.getSocketServer());
|
||||||
|
|
||||||
(new Thread(socketServer)).start();
|
|
||||||
(new Thread(GameServer.INSTANCE)).start();
|
(new Thread(GameServer.INSTANCE)).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,26 +3,28 @@ package net.simon987.server;
|
|||||||
|
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for Java Property
|
* Wrapper for Java Properties class
|
||||||
*/
|
*/
|
||||||
public class ServerConfiguration {
|
public class ServerConfiguration implements IServerConfiguration {
|
||||||
|
|
||||||
/**
|
|
||||||
* Properties
|
|
||||||
*/
|
|
||||||
private Properties properties;
|
private Properties properties;
|
||||||
|
private String fileName;
|
||||||
|
|
||||||
|
public ServerConfiguration() {
|
||||||
|
this.properties = new Properties();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerConfiguration(String fileName) {
|
||||||
|
|
||||||
|
this.fileName = fileName;
|
||||||
|
|
||||||
public ServerConfiguration(String file) {
|
|
||||||
try {
|
try {
|
||||||
properties = new Properties();
|
properties = new Properties();
|
||||||
InputStream is = new FileInputStream("config.properties");
|
InputStream is = new FileInputStream(this.fileName);
|
||||||
properties.load(is);
|
properties.load(is);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -30,6 +32,17 @@ public class ServerConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveConfig() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
OutputStream os = new FileOutputStream(this.fileName);
|
||||||
|
properties.store(os, "");
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
LogManager.LOGGER.severe("Problem saving server configuration: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getInt(String key) {
|
public int getInt(String key) {
|
||||||
return Integer.valueOf((String) properties.get(key));
|
return Integer.valueOf((String) properties.get(key));
|
||||||
|
|
||||||
@ -40,4 +53,14 @@ public class ServerConfiguration {
|
|||||||
return (String) properties.get(key);
|
return (String) properties.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setInt(String key, int value) {
|
||||||
|
properties.setProperty(key, String.valueOf(value));
|
||||||
|
saveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setString(String key, String value) {
|
||||||
|
properties.setProperty(key, value);
|
||||||
|
saveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.simon987.server.assembly;
|
package net.simon987.server.assembly;
|
||||||
|
|
||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.server.IServerConfiguration;
|
||||||
import net.simon987.server.assembly.exception.*;
|
import net.simon987.server.assembly.exception.*;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import org.apache.commons.text.StringEscapeUtils;
|
import org.apache.commons.text.StringEscapeUtils;
|
||||||
@ -18,18 +18,22 @@ import java.util.regex.Pattern;
|
|||||||
*/
|
*/
|
||||||
public class Assembler {
|
public class Assembler {
|
||||||
|
|
||||||
private ServerConfiguration config;
|
private IServerConfiguration config;
|
||||||
|
|
||||||
private InstructionSet instructionSet;
|
private InstructionSet instructionSet;
|
||||||
|
|
||||||
private RegisterSet registerSet;
|
private RegisterSet registerSet;
|
||||||
|
|
||||||
private static final int MEM_SIZE = 0x10000; // Size in words todo load from config
|
private static int MEM_SIZE;
|
||||||
|
private static String labelPattern = "^\\s*[a-zA-Z_]\\w*:";
|
||||||
|
private static Pattern commentPattern = Pattern.compile("\"[^\"]*\"|(;)");
|
||||||
|
|
||||||
public Assembler(InstructionSet instructionSet, RegisterSet registerSet, ServerConfiguration config) {
|
public Assembler(InstructionSet instructionSet, RegisterSet registerSet, IServerConfiguration config) {
|
||||||
this.instructionSet = instructionSet;
|
this.instructionSet = instructionSet;
|
||||||
this.registerSet = registerSet;
|
this.registerSet = registerSet;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
|
Assembler.MEM_SIZE = config.getInt("memory_size");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,11 +43,17 @@ public class Assembler {
|
|||||||
* @return The line without its comment part
|
* @return The line without its comment part
|
||||||
*/
|
*/
|
||||||
private static String removeComment(String line) {
|
private static String removeComment(String line) {
|
||||||
if (line.indexOf(';') != -1) {
|
|
||||||
return line.substring(0, line.indexOf(';'));
|
Matcher m = commentPattern.matcher(line);
|
||||||
} else {
|
|
||||||
return line;
|
while (m.find()) {
|
||||||
|
try {
|
||||||
|
return line.substring(0, m.start(1));
|
||||||
|
} catch (IndexOutOfBoundsException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,14 +64,13 @@ public class Assembler {
|
|||||||
*/
|
*/
|
||||||
private static String removeLabel(String line) {
|
private static String removeLabel(String line) {
|
||||||
|
|
||||||
return line.replaceAll("^\\s*\\b\\w*\\b:", "");
|
return line.replaceAll(labelPattern, "");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for and save the origin
|
* Check for and save the origin
|
||||||
*
|
*
|
||||||
* @param line Current line. Assuming that the comments & labels are removed
|
* @param line Current line. Assuming that the comments and labels are removed
|
||||||
* @param result Current line number
|
* @param result Current line number
|
||||||
*/
|
*/
|
||||||
private static void checkForORGInstruction(String line, AssemblyResult result, int currentLine)
|
private static void checkForORGInstruction(String line, AssemblyResult result, int currentLine)
|
||||||
@ -97,7 +106,7 @@ public class Assembler {
|
|||||||
line = removeComment(line);
|
line = removeComment(line);
|
||||||
|
|
||||||
//Check for labels
|
//Check for labels
|
||||||
Pattern pattern = Pattern.compile("^\\s*\\b\\w*\\b:");
|
Pattern pattern = Pattern.compile(labelPattern);
|
||||||
Matcher matcher = pattern.matcher(line);
|
Matcher matcher = pattern.matcher(line);
|
||||||
|
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
@ -121,7 +130,7 @@ public class Assembler {
|
|||||||
/**
|
/**
|
||||||
* Parse the DW instruction (Define word). Handles DUP operator
|
* Parse the DW instruction (Define word). Handles DUP operator
|
||||||
*
|
*
|
||||||
* @param line Current line. assuming that comments & labels are removed
|
* @param line Current line. assuming that comments and labels are removed
|
||||||
* @param currentLine Current line number
|
* @param currentLine Current line number
|
||||||
* @param labels Map of labels
|
* @param labels Map of labels
|
||||||
* @return Encoded instruction, null if the line is not a DW instruction
|
* @return Encoded instruction, null if the line is not a DW instruction
|
||||||
@ -139,7 +148,7 @@ public class Assembler {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
//Special thanks to https://stackoverflow.com/questions/1757065/
|
//Special thanks to https://stackoverflow.com/questions/1757065/
|
||||||
String[] values = line.substring(2, line.length()).split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
|
String[] values = line.substring(2).split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
|
||||||
|
|
||||||
for (String value : values) {
|
for (String value : values) {
|
||||||
|
|
||||||
@ -155,7 +164,14 @@ public class Assembler {
|
|||||||
|
|
||||||
//Unescape the string
|
//Unescape the string
|
||||||
String string = value.substring(1, value.length() - 1);
|
String string = value.substring(1, value.length() - 1);
|
||||||
string = StringEscapeUtils.unescapeJava(string);
|
|
||||||
|
try {
|
||||||
|
string = StringEscapeUtils.unescapeJava(string);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new InvalidOperandException(
|
||||||
|
"Invalid string operand \"" + string + "\": " + e.getMessage(),
|
||||||
|
currentLine);
|
||||||
|
}
|
||||||
|
|
||||||
out.write(string.getBytes(StandardCharsets.UTF_16BE));
|
out.write(string.getBytes(StandardCharsets.UTF_16BE));
|
||||||
} else if (labels != null && labels.containsKey(value)) {
|
} else if (labels != null && labels.containsKey(value)) {
|
||||||
@ -204,6 +220,17 @@ public class Assembler {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the DW instruction (Define word). Handles DUP operator
|
||||||
|
*
|
||||||
|
* @param line Current line. assuming that comments and labels are removed
|
||||||
|
* @param currentLine Current line number
|
||||||
|
* @return Encoded instruction, null if the line is not a DW instruction
|
||||||
|
*/
|
||||||
|
private static byte[] parseDWInstruction(String line, int currentLine) throws AssemblyException {
|
||||||
|
return parseDWInstruction(line, null, currentLine);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the dup operator
|
* Parse the dup operator
|
||||||
*
|
*
|
||||||
@ -256,18 +283,7 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the DW instruction (Define word). Handles DUP operator
|
* Check for and handle section declarations (.text and .data)
|
||||||
*
|
|
||||||
* @param line Current line. assuming that comments & labels are removed
|
|
||||||
* @param currentLine Current line number
|
|
||||||
* @return Encoded instruction, null if the line is not a DW instruction
|
|
||||||
*/
|
|
||||||
private static byte[] parseDWInstruction(String line, int currentLine) throws AssemblyException {
|
|
||||||
return parseDWInstruction(line, null, currentLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for and handle section declarations (.text & .data)
|
|
||||||
*
|
*
|
||||||
* @param line Current line
|
* @param line Current line
|
||||||
*/
|
*/
|
||||||
@ -278,14 +294,14 @@ public class Assembler {
|
|||||||
|
|
||||||
if (tokens[0].toUpperCase().equals(".TEXT")) {
|
if (tokens[0].toUpperCase().equals(".TEXT")) {
|
||||||
|
|
||||||
result.defineSecton(Section.TEXT, currentLine, currentOffset);
|
result.defineSection(Section.TEXT, currentLine, currentOffset);
|
||||||
throw new PseudoInstructionException(currentLine);
|
throw new PseudoInstructionException(currentLine);
|
||||||
|
|
||||||
} else if (tokens[0].toUpperCase().equals(".DATA")) {
|
} else if (tokens[0].toUpperCase().equals(".DATA")) {
|
||||||
|
|
||||||
LogManager.LOGGER.fine("DEBUG: .data @" + currentLine);
|
LogManager.LOGGER.fine("DEBUG: .data @" + currentLine);
|
||||||
|
|
||||||
result.defineSecton(Section.DATA, currentLine, currentOffset);
|
result.defineSection(Section.DATA, currentLine, currentOffset);
|
||||||
throw new PseudoInstructionException(currentLine);
|
throw new PseudoInstructionException(currentLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -302,7 +318,7 @@ public class Assembler {
|
|||||||
/* the EQU pseudo instruction is equivalent to the #define compiler directive in C/C++
|
/* the EQU pseudo instruction is equivalent to the #define compiler directive in C/C++
|
||||||
* usage: constant_name EQU <immediate_value>
|
* usage: constant_name EQU <immediate_value>
|
||||||
* A constant treated the same way as a label.
|
* A constant treated the same way as a label.
|
||||||
*/
|
*/
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
String[] tokens = line.split("\\s+");
|
String[] tokens = line.split("\\s+");
|
||||||
|
|
||||||
@ -346,7 +362,47 @@ public class Assembler {
|
|||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
|
||||||
//Pass 1: Get code origin
|
//Pass 1: Get code origin
|
||||||
for (currentLine = 0; currentLine < lines.length; currentLine++) {
|
getCodeOrigin(lines, result);
|
||||||
|
//Pass 2: Save label names and location
|
||||||
|
saveLabelNamesAndLocation(lines, result);
|
||||||
|
//Pass 3: encode instructions
|
||||||
|
encodeInstructions(lines, result, out);
|
||||||
|
|
||||||
|
|
||||||
|
//If the code contains OffsetOverFlowException(s), don't bother writing the assembled bytes to memory
|
||||||
|
boolean writeToMemory = true;
|
||||||
|
for (Exception e : result.exceptions) {
|
||||||
|
if (e instanceof OffsetOverflowException) {
|
||||||
|
writeToMemory = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeToMemory) {
|
||||||
|
result.bytes = out.toByteArray();
|
||||||
|
} else {
|
||||||
|
result.bytes = new byte[0];
|
||||||
|
LogManager.LOGGER.fine("Skipping writing assembled bytes to memory. (OffsetOverflowException)");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
out.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
LogManager.LOGGER.info("Assembled " + result.bytes.length + " bytes (" + result.exceptions.size() + " errors)");
|
||||||
|
for (AssemblyException e : result.exceptions) {
|
||||||
|
LogManager.LOGGER.severe(e.getMessage() + '@' + e.getLine());
|
||||||
|
}
|
||||||
|
LogManager.LOGGER.info('\n' + Util.toHex(result.bytes));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getCodeOrigin(String[] lines, AssemblyResult result) {
|
||||||
|
for (int currentLine = 0; currentLine < lines.length; currentLine++) {
|
||||||
try {
|
try {
|
||||||
checkForORGInstruction(lines[currentLine], result, currentLine);
|
checkForORGInstruction(lines[currentLine], result, currentLine);
|
||||||
|
|
||||||
@ -357,10 +413,11 @@ public class Assembler {
|
|||||||
//Ignore error
|
//Ignore error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Pass 2: Save label names and location
|
private void saveLabelNamesAndLocation(String[] lines, AssemblyResult result) {
|
||||||
int currentOffset = 0;
|
int currentOffset = 0;
|
||||||
for (currentLine = 0; currentLine < lines.length; currentLine++) {
|
for (int currentLine = 0; currentLine < lines.length; currentLine++) {
|
||||||
try {
|
try {
|
||||||
checkForLabel(lines[currentLine], result, (char)currentOffset);
|
checkForLabel(lines[currentLine], result, (char)currentOffset);
|
||||||
|
|
||||||
@ -378,11 +435,11 @@ public class Assembler {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encodeInstructions(String[] lines, AssemblyResult result, ByteArrayOutputStream out) {
|
||||||
//Pass 3: encode instructions
|
int currentOffset = 0;
|
||||||
currentOffset = 0;
|
for (int currentLine = 0; currentLine < lines.length; currentLine++) {
|
||||||
for (currentLine = 0; currentLine < lines.length; currentLine++) {
|
|
||||||
|
|
||||||
String line = lines[currentLine];
|
String line = lines[currentLine];
|
||||||
|
|
||||||
@ -423,36 +480,6 @@ public class Assembler {
|
|||||||
ioE.printStackTrace();
|
ioE.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//If the code contains OffsetOverFlowException(s), don't bother writing the assembled bytes to memory
|
|
||||||
boolean writeToMemory = true;
|
|
||||||
for (Exception e : result.exceptions) {
|
|
||||||
if (e instanceof OffsetOverflowException) {
|
|
||||||
writeToMemory = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (writeToMemory) {
|
|
||||||
result.bytes = out.toByteArray();
|
|
||||||
} else {
|
|
||||||
result.bytes = new byte[0];
|
|
||||||
LogManager.LOGGER.fine("Skipping writing assembled bytes to memory. (OffsetOverflowException)");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
out.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
LogManager.LOGGER.info("Assembled " + result.bytes.length + " bytes (" + result.exceptions.size() + " errors)");
|
|
||||||
for (AssemblyException e : result.exceptions) {
|
|
||||||
LogManager.LOGGER.severe(e.getMessage() + '@' + e.getLine());
|
|
||||||
}
|
|
||||||
LogManager.LOGGER.info('\n' + Util.toHex(result.bytes));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -528,13 +555,13 @@ public class Assembler {
|
|||||||
|
|
||||||
if (instructionSet.get(mnemonic) == null) {
|
if (instructionSet.get(mnemonic) == null) {
|
||||||
throw new InvalidMnemonicException(mnemonic, currentLine);
|
throw new InvalidMnemonicException(mnemonic, currentLine);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check operands and encode instruction
|
//Check operands and encode instruction
|
||||||
|
final int beginIndex = line.indexOf(mnemonic) + mnemonic.length();
|
||||||
if (line.contains(",")) {
|
if (line.contains(",")) {
|
||||||
//2 operands
|
//2 operands
|
||||||
String strO1 = line.substring(line.indexOf(mnemonic) + mnemonic.length(), line.indexOf(','));
|
String strO1 = line.substring(beginIndex, line.indexOf(','));
|
||||||
String strO2 = line.substring(line.indexOf(','));
|
String strO2 = line.substring(line.indexOf(','));
|
||||||
|
|
||||||
Operand o1, o2;
|
Operand o1, o2;
|
||||||
@ -554,7 +581,7 @@ public class Assembler {
|
|||||||
} else if (tokens.length > 1) {
|
} else if (tokens.length > 1) {
|
||||||
//1 operand
|
//1 operand
|
||||||
|
|
||||||
String strO1 = line.substring(line.indexOf(mnemonic) + mnemonic.length());
|
String strO1 = line.substring(beginIndex);
|
||||||
|
|
||||||
Operand o1;
|
Operand o1;
|
||||||
if (assumeLabels) {
|
if (assumeLabels) {
|
||||||
@ -575,6 +602,5 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return out.toByteArray();
|
return out.toByteArray();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.simon987.server.assembly;
|
package net.simon987.server.assembly;
|
||||||
|
|
||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.server.IServerConfiguration;
|
||||||
import net.simon987.server.assembly.exception.AssemblyException;
|
import net.simon987.server.assembly.exception.AssemblyException;
|
||||||
import net.simon987.server.assembly.exception.DuplicateSectionException;
|
import net.simon987.server.assembly.exception.DuplicateSectionException;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
@ -59,7 +59,7 @@ public class AssemblyResult {
|
|||||||
*/
|
*/
|
||||||
private boolean dataSectionSet = false;
|
private boolean dataSectionSet = false;
|
||||||
|
|
||||||
AssemblyResult(ServerConfiguration config) {
|
AssemblyResult(IServerConfiguration config) {
|
||||||
origin = config.getInt("org_offset");
|
origin = config.getInt("org_offset");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ public class AssemblyResult {
|
|||||||
* @param currentLine Line number of the section declaration
|
* @param currentLine Line number of the section declaration
|
||||||
* @throws DuplicateSectionException when a section is defined twice
|
* @throws DuplicateSectionException when a section is defined twice
|
||||||
*/
|
*/
|
||||||
void defineSecton(Section section, int currentLine, int currentOffset) throws DuplicateSectionException {
|
void defineSection(Section section, int currentLine, int currentOffset) throws DuplicateSectionException {
|
||||||
|
|
||||||
if (section == Section.TEXT) {
|
if (section == Section.TEXT) {
|
||||||
//Code section
|
//Code section
|
||||||
|
@ -1,26 +1,23 @@
|
|||||||
package net.simon987.server.assembly;
|
package net.simon987.server.assembly;
|
||||||
|
|
||||||
import com.mongodb.BasicDBList;
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.server.IServerConfiguration;
|
||||||
import net.simon987.server.assembly.exception.CancelledException;
|
import net.simon987.server.assembly.exception.CancelledException;
|
||||||
import net.simon987.server.assembly.instruction.*;
|
import net.simon987.server.assembly.instruction.*;
|
||||||
import net.simon987.server.event.CpuInitialisationEvent;
|
import net.simon987.server.event.CpuInitialisationEvent;
|
||||||
import net.simon987.server.event.GameEvent;
|
import net.simon987.server.event.GameEvent;
|
||||||
import net.simon987.server.io.MongoSerialisable;
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import net.simon987.server.game.objects.HardwareHost;
|
||||||
|
import net.simon987.server.io.MongoSerializable;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import net.simon987.server.user.User;
|
import org.bson.Document;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CPU: Central Processing Unit. A CPU is capable of reading bytes from
|
* CPU: Central Processing Unit. A CPU is capable of reading bytes from
|
||||||
* a Memory object and execute them. A CPU object holds registers objects &
|
* a Memory object and execute them. A CPU object holds registers objects and
|
||||||
* a Memory object.
|
* a Memory object.
|
||||||
*/
|
*/
|
||||||
public class CPU implements MongoSerialisable {
|
public class CPU implements MongoSerializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -54,25 +51,56 @@ public class CPU implements MongoSerialisable {
|
|||||||
private int ip;
|
private int ip;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of attached hardware, 'modules'
|
* Hardware is connected to the hardwareHost
|
||||||
*/
|
*/
|
||||||
private HashMap<Integer, CpuHardware> attachedHardware;
|
private HardwareHost hardwareHost;
|
||||||
|
|
||||||
private ServerConfiguration config;
|
|
||||||
|
|
||||||
private int registerSetSize;
|
private int registerSetSize;
|
||||||
|
|
||||||
private static final char EXECUTION_COST_ADDR = 0x0050;
|
private static final char EXECUTION_COST_ADDR = 0x0050;
|
||||||
private static final char EXECUTED_INS_ADDR = 0x0051;
|
private static final char EXECUTED_INS_ADDR = 0x0051;
|
||||||
|
|
||||||
|
public CPU() {
|
||||||
|
instructionSet = new DefaultInstructionSet();
|
||||||
|
registerSet = new DefaultRegisterSet();
|
||||||
|
codeSectionOffset = GameServer.INSTANCE.getConfig().getInt("org_offset");
|
||||||
|
|
||||||
|
instructionSet.add(new JmpInstruction(this));
|
||||||
|
instructionSet.add(new JnzInstruction(this));
|
||||||
|
instructionSet.add(new JzInstruction(this));
|
||||||
|
instructionSet.add(new JgInstruction(this));
|
||||||
|
instructionSet.add(new JgeInstruction(this));
|
||||||
|
instructionSet.add(new JleInstruction(this));
|
||||||
|
instructionSet.add(new JlInstruction(this));
|
||||||
|
instructionSet.add(new PushInstruction(this));
|
||||||
|
instructionSet.add(new PopInstruction(this));
|
||||||
|
instructionSet.add(new CallInstruction(this));
|
||||||
|
instructionSet.add(new RetInstruction(this));
|
||||||
|
instructionSet.add(new MulInstruction(this));
|
||||||
|
instructionSet.add(new DivInstruction(this));
|
||||||
|
instructionSet.add(new JnsInstruction(this));
|
||||||
|
instructionSet.add(new JsInstruction(this));
|
||||||
|
instructionSet.add(new HwiInstruction(this));
|
||||||
|
instructionSet.add(new HwqInstruction(this));
|
||||||
|
instructionSet.add(new XchgInstruction(this));
|
||||||
|
instructionSet.add(new JcInstruction(this));
|
||||||
|
instructionSet.add(new JncInstruction(this));
|
||||||
|
instructionSet.add(new JnoInstruction(this));
|
||||||
|
instructionSet.add(new JoInstruction(this));
|
||||||
|
instructionSet.add(new PushfInstruction(this));
|
||||||
|
instructionSet.add(new PopfInstruction(this));
|
||||||
|
instructionSet.add(new JnaInstruction(this));
|
||||||
|
instructionSet.add(new JaInstruction(this));
|
||||||
|
|
||||||
|
status = new Status();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new CPU
|
* Creates a new CPU
|
||||||
*/
|
*/
|
||||||
public CPU(ServerConfiguration config, User user) throws CancelledException {
|
public CPU(IServerConfiguration config, ControllableUnit unit) throws CancelledException {
|
||||||
this.config = config;
|
|
||||||
instructionSet = new DefaultInstructionSet();
|
instructionSet = new DefaultInstructionSet();
|
||||||
registerSet = new DefaultRegisterSet();
|
registerSet = new DefaultRegisterSet();
|
||||||
attachedHardware = new HashMap<>();
|
|
||||||
codeSectionOffset = config.getInt("org_offset");
|
codeSectionOffset = config.getInt("org_offset");
|
||||||
|
|
||||||
instructionSet.add(new JmpInstruction(this));
|
instructionSet.add(new JmpInstruction(this));
|
||||||
@ -105,7 +133,7 @@ public class CPU implements MongoSerialisable {
|
|||||||
status = new Status();
|
status = new Status();
|
||||||
memory = new Memory(config.getInt("memory_size"));
|
memory = new Memory(config.getInt("memory_size"));
|
||||||
|
|
||||||
GameEvent event = new CpuInitialisationEvent(this, user);
|
GameEvent event = new CpuInitialisationEvent(this, unit);
|
||||||
GameServer.INSTANCE.getEventDispatcher().dispatch(event);
|
GameServer.INSTANCE.getEventDispatcher().dispatch(event);
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
@ -160,7 +188,7 @@ public class CPU implements MongoSerialisable {
|
|||||||
}
|
}
|
||||||
int elapsed = (int) (System.currentTimeMillis() - startTime);
|
int elapsed = (int) (System.currentTimeMillis() - startTime);
|
||||||
|
|
||||||
LogManager.LOGGER.fine(counter + " instruction in " + elapsed + "ms : " + (double) counter / (elapsed / 1000) / 1000000 + "MHz");
|
// LogManager.LOGGER.fine(counter + " instruction in " + elapsed + "ms : " + (double) counter / (elapsed / 1000) / 1000000 + "MHz");
|
||||||
|
|
||||||
|
|
||||||
//Write execution cost and instruction count to memory
|
//Write execution cost and instruction count to memory
|
||||||
@ -173,111 +201,17 @@ public class CPU implements MongoSerialisable {
|
|||||||
|
|
||||||
public void executeInstruction(Instruction instruction, int source, int destination) {
|
public void executeInstruction(Instruction instruction, int source, int destination) {
|
||||||
|
|
||||||
|
|
||||||
//Execute the instruction
|
//Execute the instruction
|
||||||
if (source == 0) {
|
if (source == 0) {
|
||||||
//No operand (assuming that destination is also null)
|
//No operand (assuming that destination is also null)
|
||||||
ip++;
|
ip++;
|
||||||
instruction.execute(status);
|
instruction.execute(status);
|
||||||
} else if (source == Operand.IMMEDIATE_VALUE) {
|
} else if (source == Operand.IMMEDIATE_VALUE) {
|
||||||
ip++;
|
executeImmediateValue(instruction, source, destination);
|
||||||
int sourceValue = memory.get(ip);
|
|
||||||
|
|
||||||
if (destination == 0) {
|
|
||||||
//Single operand
|
|
||||||
ip++;
|
|
||||||
instruction.execute(sourceValue, status);
|
|
||||||
} else if (destination == Operand.IMMEDIATE_VALUE) {
|
|
||||||
//Destination is an immediate value too
|
|
||||||
//this shouldn't happen
|
|
||||||
LogManager.LOGGER.severe("Trying to execute an instruction with 2" +
|
|
||||||
"immediate values as operands"); //todo remove debug info
|
|
||||||
|
|
||||||
} else if (destination == Operand.IMMEDIATE_VALUE_MEM) {
|
|
||||||
//Destination is memory immediate
|
|
||||||
ip += 2;
|
|
||||||
instruction.execute(memory, memory.get(ip - 1), sourceValue, status);
|
|
||||||
} else if (destination <= registerSetSize) {
|
|
||||||
//Destination is a register
|
|
||||||
ip++;
|
|
||||||
instruction.execute(registerSet, destination, sourceValue, status);
|
|
||||||
|
|
||||||
} else if (destination <= registerSetSize * 2) {
|
|
||||||
//Destination is [reg]
|
|
||||||
ip++;
|
|
||||||
instruction.execute(memory, registerSet.get(destination - registerSetSize), sourceValue, status);
|
|
||||||
} else {
|
|
||||||
//Assuming that destination is [reg + x]
|
|
||||||
ip += 2;
|
|
||||||
instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1),
|
|
||||||
sourceValue, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (source == Operand.IMMEDIATE_VALUE_MEM) {
|
} else if (source == Operand.IMMEDIATE_VALUE_MEM) {
|
||||||
//Source is [x]
|
executeImmediateValueMem(instruction, source, destination);
|
||||||
ip++;
|
|
||||||
int sourceValue = memory.get(memory.get(ip));
|
|
||||||
|
|
||||||
if (destination == 0) {
|
|
||||||
//Single operand
|
|
||||||
ip++;
|
|
||||||
instruction.execute(memory, memory.get(ip - 1), status);
|
|
||||||
} else if (destination == Operand.IMMEDIATE_VALUE) {
|
|
||||||
//Destination is an immediate value
|
|
||||||
|
|
||||||
//this shouldn't happen
|
|
||||||
LogManager.LOGGER.severe("Trying to execute an instruction with an" +
|
|
||||||
"immediate values as dst operand"); //todo remove debug info
|
|
||||||
} else if (destination == Operand.IMMEDIATE_VALUE_MEM) {
|
|
||||||
//Destination is memory immediate too
|
|
||||||
ip += 2;
|
|
||||||
instruction.execute(memory, memory.get(ip - 1), sourceValue, status);
|
|
||||||
} else if (destination <= registerSetSize) {
|
|
||||||
//Destination is a register
|
|
||||||
ip++;
|
|
||||||
instruction.execute(registerSet, destination, sourceValue, status);
|
|
||||||
} else if (destination <= registerSetSize * 2) {
|
|
||||||
//Destination is [reg]
|
|
||||||
ip++;
|
|
||||||
instruction.execute(memory, registerSet.get(destination - registerSetSize), sourceValue, status);
|
|
||||||
} else {
|
|
||||||
//Assuming that destination is [reg + x]
|
|
||||||
ip += 2;
|
|
||||||
instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1), sourceValue, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (source <= registerSetSize) {
|
} else if (source <= registerSetSize) {
|
||||||
//Source is a register
|
executeSourceIsRegister(instruction, source, destination);
|
||||||
|
|
||||||
if (destination == 0) {
|
|
||||||
//Single operand
|
|
||||||
ip++;
|
|
||||||
instruction.execute(registerSet, source, status);
|
|
||||||
|
|
||||||
} else if (destination == Operand.IMMEDIATE_VALUE) {
|
|
||||||
//Destination is an immediate value
|
|
||||||
//this shouldn't happen
|
|
||||||
LogManager.LOGGER.severe("Trying to execute an instruction with an" +
|
|
||||||
"immediate values as dst operand"); //todo remove debug info
|
|
||||||
} else if (destination == Operand.IMMEDIATE_VALUE_MEM) {
|
|
||||||
//Destination is memory immediate
|
|
||||||
ip += 2;
|
|
||||||
instruction.execute(memory, memory.get(ip - 1), registerSet, source, status);
|
|
||||||
} else if (destination <= registerSetSize) {
|
|
||||||
//Destination is a register too
|
|
||||||
ip++;
|
|
||||||
instruction.execute(registerSet, destination, registerSet, source, status);
|
|
||||||
} else if (destination <= registerSetSize * 2) {
|
|
||||||
//Destination is [reg]
|
|
||||||
ip++;
|
|
||||||
instruction.execute(memory, registerSet.get(destination - registerSetSize), registerSet, source, status);
|
|
||||||
} else {
|
|
||||||
//Assuming that destination is [reg + x]
|
|
||||||
ip += 2;
|
|
||||||
instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1),
|
|
||||||
registerSet, source, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (source <= registerSetSize * 2) {
|
} else if (source <= registerSetSize * 2) {
|
||||||
//Source is [reg]
|
//Source is [reg]
|
||||||
if (destination == 0) {
|
if (destination == 0) {
|
||||||
@ -347,48 +281,129 @@ public class CPU implements MongoSerialisable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void executeSourceIsRegister(Instruction instruction, int source, int destination) {
|
||||||
|
//Source is a register
|
||||||
|
if (destination == 0) {
|
||||||
|
//Single operand
|
||||||
|
ip++;
|
||||||
|
instruction.execute(registerSet, source, status);
|
||||||
|
|
||||||
|
} else if (destination == Operand.IMMEDIATE_VALUE) {
|
||||||
|
//Destination is an immediate value
|
||||||
|
//this shouldn't happen
|
||||||
|
LogManager.LOGGER.severe("Trying to execute an instruction with an" +
|
||||||
|
"immediate values as dst operand"); //todo remove debug info
|
||||||
|
} else if (destination == Operand.IMMEDIATE_VALUE_MEM) {
|
||||||
|
//Destination is memory immediate
|
||||||
|
ip += 2;
|
||||||
|
instruction.execute(memory, memory.get(ip - 1), registerSet, source, status);
|
||||||
|
} else if (destination <= registerSetSize) {
|
||||||
|
//Destination is a register too
|
||||||
|
ip++;
|
||||||
|
instruction.execute(registerSet, destination, registerSet, source, status);
|
||||||
|
} else if (destination <= registerSetSize * 2) {
|
||||||
|
//Destination is [reg]
|
||||||
|
ip++;
|
||||||
|
instruction.execute(memory, registerSet.get(destination - registerSetSize), registerSet, source, status);
|
||||||
|
} else {
|
||||||
|
//Assuming that destination is [reg + x]
|
||||||
|
ip += 2;
|
||||||
|
instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1),
|
||||||
|
registerSet, source, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeImmediateValue(Instruction instruction, int source, int destination) {
|
||||||
|
ip++;
|
||||||
|
int sourceValue = memory.get(ip);
|
||||||
|
|
||||||
|
if (destination == 0) {
|
||||||
|
//Single operand
|
||||||
|
ip++;
|
||||||
|
instruction.execute(sourceValue, status);
|
||||||
|
} else if (destination == Operand.IMMEDIATE_VALUE) {
|
||||||
|
//Destination is an immediate value too
|
||||||
|
//this shouldn't happen
|
||||||
|
LogManager.LOGGER.severe("Trying to execute an instruction with 2" +
|
||||||
|
"immediate values as operands"); //todo remove debug info
|
||||||
|
|
||||||
|
} else if (destination == Operand.IMMEDIATE_VALUE_MEM) {
|
||||||
|
//Destination is memory immediate
|
||||||
|
ip += 2;
|
||||||
|
instruction.execute(memory, memory.get(ip - 1), sourceValue, status);
|
||||||
|
} else if (destination <= registerSetSize) {
|
||||||
|
//Destination is a register
|
||||||
|
ip++;
|
||||||
|
instruction.execute(registerSet, destination, sourceValue, status);
|
||||||
|
|
||||||
|
} else if (destination <= registerSetSize * 2) {
|
||||||
|
//Destination is [reg]
|
||||||
|
ip++;
|
||||||
|
instruction.execute(memory, registerSet.get(destination - registerSetSize), sourceValue, status);
|
||||||
|
} else {
|
||||||
|
//Assuming that destination is [reg + x]
|
||||||
|
ip += 2;
|
||||||
|
instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1),
|
||||||
|
sourceValue, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeImmediateValueMem(Instruction instruction, int source, int destination) {
|
||||||
|
//Source is [x]
|
||||||
|
ip++;
|
||||||
|
int sourceValue = memory.get(memory.get(ip));
|
||||||
|
|
||||||
|
if (destination == 0) {
|
||||||
|
//Single operand
|
||||||
|
ip++;
|
||||||
|
instruction.execute(memory, memory.get(ip - 1), status);
|
||||||
|
} else if (destination == Operand.IMMEDIATE_VALUE) {
|
||||||
|
//Destination is an immediate value
|
||||||
|
|
||||||
|
//this shouldn't happen
|
||||||
|
LogManager.LOGGER.severe("Trying to execute an instruction with an" +
|
||||||
|
"immediate values as dst operand"); //todo remove debug info
|
||||||
|
} else if (destination == Operand.IMMEDIATE_VALUE_MEM) {
|
||||||
|
//Destination is memory immediate too
|
||||||
|
ip += 2;
|
||||||
|
instruction.execute(memory, memory.get(ip - 1), sourceValue, status);
|
||||||
|
} else if (destination <= registerSetSize) {
|
||||||
|
//Destination is a register
|
||||||
|
ip++;
|
||||||
|
instruction.execute(registerSet, destination, sourceValue, status);
|
||||||
|
} else if (destination <= registerSetSize * 2) {
|
||||||
|
//Destination is [reg]
|
||||||
|
ip++;
|
||||||
|
instruction.execute(memory, registerSet.get(destination - registerSetSize), sourceValue, status);
|
||||||
|
} else {
|
||||||
|
//Assuming that destination is [reg + x]
|
||||||
|
ip += 2;
|
||||||
|
instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1), sourceValue, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public Document mongoSerialise() {
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
Document dbObject = new Document();
|
||||||
|
|
||||||
dbObject.put("memory", memory.mongoSerialise());
|
dbObject.put("memory", memory.mongoSerialise());
|
||||||
|
|
||||||
dbObject.put("registerSet", registerSet.mongoSerialise());
|
dbObject.put("registerSet", registerSet.mongoSerialise());
|
||||||
dbObject.put("codeSegmentOffset", codeSectionOffset);
|
dbObject.put("codeSegmentOffset", codeSectionOffset);
|
||||||
|
|
||||||
BasicDBList hardwareList = new BasicDBList();
|
|
||||||
|
|
||||||
for (Integer address : attachedHardware.keySet()) {
|
|
||||||
|
|
||||||
CpuHardware hardware = attachedHardware.get(address);
|
|
||||||
|
|
||||||
BasicDBObject serialisedHw = hardware.mongoSerialise();
|
|
||||||
serialisedHw.put("address", address);
|
|
||||||
hardwareList.add(serialisedHw);
|
|
||||||
}
|
|
||||||
|
|
||||||
dbObject.put("hardware", hardwareList);
|
|
||||||
|
|
||||||
return dbObject;
|
return dbObject;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CPU deserialize(DBObject obj, User user) throws CancelledException {
|
public static CPU deserialize(Document obj, ControllableUnit unit) throws CancelledException {
|
||||||
|
|
||||||
CPU cpu = new CPU(GameServer.INSTANCE.getConfig(), user);
|
CPU cpu = new CPU(GameServer.INSTANCE.getConfig(), unit);
|
||||||
|
|
||||||
cpu.codeSectionOffset = (int) obj.get("codeSegmentOffset");
|
cpu.codeSectionOffset = obj.getInteger("codeSegmentOffset");
|
||||||
|
|
||||||
BasicDBList hardwareList = (BasicDBList) obj.get("hardware");
|
cpu.memory = new Memory((Document) obj.get("memory"));
|
||||||
|
cpu.registerSet = RegisterSet.deserialize((Document) obj.get("registerSet"));
|
||||||
for (Object serialisedHw : hardwareList) {
|
|
||||||
CpuHardware hardware = CpuHardware.deserialize((DBObject) serialisedHw);
|
|
||||||
hardware.setCpu(cpu);
|
|
||||||
cpu.attachHardware(hardware, (int) ((BasicDBObject) serialisedHw).get("address"));
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu.memory = Memory.deserialize((DBObject) obj.get("memory"));
|
|
||||||
cpu.registerSet = RegisterSet.deserialize((DBObject) obj.get("registerSet"));
|
|
||||||
|
|
||||||
return cpu;
|
return cpu;
|
||||||
|
|
||||||
@ -406,6 +421,14 @@ public class CPU implements MongoSerialisable {
|
|||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMemory(Memory memory) {
|
||||||
|
this.memory = memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegisterSet(RegisterSet registerSet) {
|
||||||
|
this.registerSet = registerSet;
|
||||||
|
}
|
||||||
|
|
||||||
public Status getStatus() {
|
public Status getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -418,56 +441,29 @@ public class CPU implements MongoSerialisable {
|
|||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCodeSectionOffset() {
|
||||||
|
return codeSectionOffset;
|
||||||
|
}
|
||||||
|
|
||||||
public void setCodeSectionOffset(int codeSectionOffset) {
|
public void setCodeSectionOffset(int codeSectionOffset) {
|
||||||
this.codeSectionOffset = codeSectionOffset;
|
this.codeSectionOffset = codeSectionOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void attachHardware(CpuHardware hardware, int address) {
|
|
||||||
attachedHardware.put(address, hardware);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void detachHardware(int address) {
|
|
||||||
attachedHardware.remove(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hardwareInterrupt(int address) {
|
|
||||||
CpuHardware hardware = attachedHardware.get(address);
|
|
||||||
|
|
||||||
if (hardware != null) {
|
|
||||||
hardware.handleInterrupt(status);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hardwareQuery(int address) {
|
|
||||||
CpuHardware hardware = attachedHardware.get(address);
|
|
||||||
|
|
||||||
if (hardware != null) {
|
|
||||||
|
|
||||||
registerSet.getRegister("B").setValue(hardware.getId());
|
|
||||||
} else {
|
|
||||||
registerSet.getRegister("B").setValue(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
||||||
String str = "------------------------\n";
|
String str = registerSet.toString();
|
||||||
str += registerSet.toString();
|
|
||||||
str += status.toString();
|
str += status.toString();
|
||||||
str += "------------------------\n";
|
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CpuHardware getHardware(int address) {
|
public HardwareHost getHardwareHost() {
|
||||||
|
return hardwareHost;
|
||||||
return attachedHardware.get(address);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHardwareHost(HardwareHost hardwareHost) {
|
||||||
|
this.hardwareHost = hardwareHost;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
package net.simon987.server.assembly;
|
|
||||||
|
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
|
||||||
import net.simon987.server.io.CpuHardwareDeserializer;
|
|
||||||
import net.simon987.server.io.MongoSerialisable;
|
|
||||||
import net.simon987.server.plugin.ServerPlugin;
|
|
||||||
|
|
||||||
public abstract class CpuHardware implements MongoSerialisable {
|
|
||||||
|
|
||||||
CPU cpu;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle an HWI instruction
|
|
||||||
*/
|
|
||||||
public abstract void handleInterrupt(Status status);
|
|
||||||
|
|
||||||
public CPU getCpu() {
|
|
||||||
return cpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCpu(CPU cpu) {
|
|
||||||
this.cpu = cpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract char getId();
|
|
||||||
|
|
||||||
public static CpuHardware deserialize(DBObject obj) {
|
|
||||||
|
|
||||||
for (ServerPlugin plugin : GameServer.INSTANCE.getPluginManager().getPlugins()) {
|
|
||||||
|
|
||||||
if (plugin instanceof CpuHardwareDeserializer) {
|
|
||||||
CpuHardware hw = ((CpuHardwareDeserializer) plugin).deserializeHardware(obj);
|
|
||||||
|
|
||||||
if (hw != null) {
|
|
||||||
return hw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,9 +1,9 @@
|
|||||||
package net.simon987.server.assembly;
|
package net.simon987.server.assembly;
|
||||||
|
|
||||||
import net.simon987.server.assembly.instruction.*;
|
import net.simon987.server.assembly.instruction.*;
|
||||||
import net.simon987.server.logging.LogManager;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default instruction set for the CPU
|
* Default instruction set for the CPU
|
||||||
@ -13,7 +13,12 @@ public class DefaultInstructionSet implements InstructionSet {
|
|||||||
/**
|
/**
|
||||||
* Map of instructions, stored in opcode : Instruction format
|
* Map of instructions, stored in opcode : Instruction format
|
||||||
*/
|
*/
|
||||||
private HashMap<Integer, Instruction> instructionMap = new HashMap<>(32);
|
private Map<Integer, Instruction> instructionMap = new HashMap<>(32);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of aliasses, stored in mnemonic : Instruction format
|
||||||
|
*/
|
||||||
|
private Map<String, Instruction> aliasesMap = new HashMap<>(16);
|
||||||
|
|
||||||
private Instruction defaultInstruction;
|
private Instruction defaultInstruction;
|
||||||
|
|
||||||
@ -32,7 +37,6 @@ public class DefaultInstructionSet implements InstructionSet {
|
|||||||
add(new AndInstruction());
|
add(new AndInstruction());
|
||||||
add(new OrInstruction());
|
add(new OrInstruction());
|
||||||
add(new ShlInstruction());
|
add(new ShlInstruction());
|
||||||
add(new SalInstruction()); //Alias is added
|
|
||||||
add(new ShrInstruction());
|
add(new ShrInstruction());
|
||||||
add(new XorInstruction());
|
add(new XorInstruction());
|
||||||
add(new TestInstruction());
|
add(new TestInstruction());
|
||||||
@ -46,6 +50,40 @@ public class DefaultInstructionSet implements InstructionSet {
|
|||||||
add(new SarInstruction());
|
add(new SarInstruction());
|
||||||
add(new IncInstruction());
|
add(new IncInstruction());
|
||||||
add(new DecInstruction());
|
add(new DecInstruction());
|
||||||
|
|
||||||
|
// 'abstract' instruction
|
||||||
|
add(new SetccInstruction());
|
||||||
|
|
||||||
|
// aliases
|
||||||
|
add(new SalInstruction());
|
||||||
|
|
||||||
|
// Setcc family
|
||||||
|
add(new SetaeInstruction());
|
||||||
|
add(new SetaInstruction());
|
||||||
|
add(new SetbeInstruction());
|
||||||
|
add(new SetbInstruction());
|
||||||
|
add(new SetcInstruction());
|
||||||
|
add(new SeteInstruction());
|
||||||
|
add(new SetgeInstruction());
|
||||||
|
add(new SetgInstruction());
|
||||||
|
add(new SetleInstruction());
|
||||||
|
add(new SetlInstruction());
|
||||||
|
add(new SetnaeInstruction());
|
||||||
|
add(new SetnaInstruction());
|
||||||
|
add(new SetnbeInstruction());
|
||||||
|
add(new SetnbInstruction());
|
||||||
|
add(new SetncInstruction());
|
||||||
|
add(new SetneInstruction());
|
||||||
|
add(new SetngeInstruction());
|
||||||
|
add(new SetngInstruction());
|
||||||
|
add(new SetnleInstruction());
|
||||||
|
add(new SetnlInstruction());
|
||||||
|
add(new SetnoInstruction());
|
||||||
|
add(new SetnsInstruction());
|
||||||
|
add(new SetnzInstruction());
|
||||||
|
add(new SetoInstruction());
|
||||||
|
add(new SetsInstruction());
|
||||||
|
add(new SetzInstruction());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,7 +104,24 @@ public class DefaultInstructionSet implements InstructionSet {
|
|||||||
return defaultInstruction;
|
return defaultInstruction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Get an instruction from its mnemonic
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Instruction get(String mnemonic) {
|
||||||
|
for (Instruction ins : instructionMap.values()) {
|
||||||
|
if (ins.getMnemonic().equalsIgnoreCase(mnemonic)) {
|
||||||
|
return ins;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Instruction aliasedInstruction = aliasesMap.get(mnemonic.toLowerCase());
|
||||||
|
if (aliasedInstruction != null) {
|
||||||
|
return aliasedInstruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Add a new instruction to the instructionSet
|
* Add a new instruction to the instructionSet
|
||||||
*
|
*
|
||||||
@ -77,27 +132,13 @@ public class DefaultInstructionSet implements InstructionSet {
|
|||||||
instructionMap.put(opcode, instruction);
|
instructionMap.put(opcode, instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Instruction get(String mnemonic) {
|
|
||||||
for (Instruction ins : instructionMap.values()) {
|
|
||||||
if (ins.getMnemonic().equalsIgnoreCase(mnemonic)) {
|
|
||||||
return ins;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(Instruction instruction) {
|
public void add(Instruction instruction) {
|
||||||
if (instructionMap.containsKey(instruction.getOpCode())) {
|
Instruction aliasedInstruction = instructionMap.get(instruction.getOpCode());
|
||||||
LogManager.LOGGER.fine(instruction.getMnemonic() + " instruction is an alias for " +
|
if (aliasedInstruction != null) {
|
||||||
instructionMap.get(instruction.getOpCode()).getMnemonic());
|
aliasesMap.put(instruction.getMnemonic(), instruction);
|
||||||
} else {
|
} else {
|
||||||
instructionMap.put(instruction.getOpCode(), instruction);
|
instructionMap.put(instruction.getOpCode(), instruction);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
package net.simon987.server.assembly;
|
||||||
|
|
||||||
|
|
||||||
|
import net.simon987.server.game.objects.ControllableUnit;
|
||||||
|
import net.simon987.server.io.JSONSerializable;
|
||||||
|
import net.simon987.server.io.MongoSerializable;
|
||||||
|
import org.bson.Document;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class HardwareModule implements MongoSerializable, JSONSerializable {
|
||||||
|
|
||||||
|
private CPU cpu;
|
||||||
|
protected ControllableUnit unit;
|
||||||
|
|
||||||
|
public HardwareModule() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public HardwareModule(Document document, ControllableUnit unit) {
|
||||||
|
this.unit = unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an HWI instruction
|
||||||
|
*/
|
||||||
|
public abstract void handleInterrupt(Status status);
|
||||||
|
|
||||||
|
protected CPU getCpu() {
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCpu(CPU cpu) {
|
||||||
|
this.cpu = cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract char getId();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
JSONObject hwJson = jsonSerialise();
|
||||||
|
return String.format("{%s: {%s}}", getClass().getSimpleName(), hwJson == null ? "" : hwJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject jsonSerialise() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject debugJsonSerialise() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Document mongoSerialise() {
|
||||||
|
Document document = new Document();
|
||||||
|
|
||||||
|
document.put("type", getClass().getCanonicalName());
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package net.simon987.server.assembly;
|
package net.simon987.server.assembly;
|
||||||
|
|
||||||
|
import net.simon987.server.assembly.exception.AssemblyException;
|
||||||
import net.simon987.server.assembly.exception.IllegalOperandException;
|
import net.simon987.server.assembly.exception.IllegalOperandException;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@ -102,7 +102,7 @@ public abstract class Instruction {
|
|||||||
* @param o2 Source operand
|
* @param o2 Source operand
|
||||||
* @return true if valid
|
* @return true if valid
|
||||||
*/
|
*/
|
||||||
private static boolean operandsValid(Operand o1, Operand o2) throws IllegalOperandException {
|
public boolean operandsValid(Operand o1, Operand o2) {
|
||||||
return o1.getType() != OperandType.IMMEDIATE16;
|
return o1.getType() != OperandType.IMMEDIATE16;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ public abstract class Instruction {
|
|||||||
* @param o1 source operand
|
* @param o1 source operand
|
||||||
* @return true if the specified operand can be used with this instruction
|
* @return true if the specified operand can be used with this instruction
|
||||||
*/
|
*/
|
||||||
private static boolean operandValid(Operand o1) {
|
public boolean operandValid(Operand o1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ public abstract class Instruction {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getMnemonic() {
|
public String getMnemonic() {
|
||||||
return mnemonic;
|
return mnemonic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ public abstract class Instruction {
|
|||||||
*
|
*
|
||||||
* @param out encoded bytes will be written here
|
* @param out encoded bytes will be written here
|
||||||
*/
|
*/
|
||||||
void encode(ByteArrayOutputStream out, int currentLine) throws IllegalOperandException {
|
public void encode(ByteArrayOutputStream out, int currentLine) throws AssemblyException {
|
||||||
|
|
||||||
if (!noOperandsValid()) {
|
if (!noOperandsValid()) {
|
||||||
throw new IllegalOperandException("This instruction must have operand(s)!", currentLine);
|
throw new IllegalOperandException("This instruction must have operand(s)!", currentLine);
|
||||||
@ -147,8 +147,8 @@ public abstract class Instruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void encode(ByteArrayOutputStream out, Operand o1, Operand o2, int currentLine)
|
public void encode(ByteArrayOutputStream out, Operand o1, Operand o2, int currentLine)
|
||||||
throws IllegalOperandException {
|
throws AssemblyException {
|
||||||
MachineCode code = new MachineCode();
|
MachineCode code = new MachineCode();
|
||||||
code.writeOpcode(opCode);
|
code.writeOpcode(opCode);
|
||||||
|
|
||||||
@ -182,8 +182,8 @@ public abstract class Instruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void encode(ByteArrayOutputStream out, Operand o1, int currentLine)
|
public void encode(ByteArrayOutputStream out, Operand o1, int currentLine)
|
||||||
throws IllegalOperandException {
|
throws AssemblyException {
|
||||||
MachineCode code = new MachineCode();
|
MachineCode code = new MachineCode();
|
||||||
code.writeOpcode(opCode);
|
code.writeOpcode(opCode);
|
||||||
|
|
||||||
@ -203,14 +203,12 @@ public abstract class Instruction {
|
|||||||
|
|
||||||
//Destination bits are left blank
|
//Destination bits are left blank
|
||||||
|
|
||||||
//System.out.println("o1: " + o1.getType());
|
|
||||||
|
|
||||||
for (byte b : code.bytes()) {
|
for (byte b : code.bytes()) {
|
||||||
out.write(b);
|
out.write(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getOpCode() {
|
public int getOpCode() {
|
||||||
return opCode;
|
return opCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import java.util.ArrayList;
|
|||||||
* Represents an encoded instruction. this class is used to easily
|
* Represents an encoded instruction. this class is used to easily
|
||||||
* write to an 16bit value.
|
* write to an 16bit value.
|
||||||
*/
|
*/
|
||||||
class MachineCode {
|
public class MachineCode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value of the initial 2-byte instruction
|
* Value of the initial 2-byte instruction
|
||||||
@ -27,7 +27,7 @@ class MachineCode {
|
|||||||
*
|
*
|
||||||
* @param opCode signed 6-bit integer (value 0-63)
|
* @param opCode signed 6-bit integer (value 0-63)
|
||||||
*/
|
*/
|
||||||
void writeOpcode(int opCode) {
|
public void writeOpcode(int opCode) {
|
||||||
|
|
||||||
if (opCode < 0 || opCode > 63) {
|
if (opCode < 0 || opCode > 63) {
|
||||||
LogManager.LOGGER.severe("Couldn't write the opCode for instruction :" + opCode);
|
LogManager.LOGGER.severe("Couldn't write the opCode for instruction :" + opCode);
|
||||||
@ -44,7 +44,7 @@ class MachineCode {
|
|||||||
*
|
*
|
||||||
* @param src signed 5-bit integer (value 0-31)
|
* @param src signed 5-bit integer (value 0-31)
|
||||||
*/
|
*/
|
||||||
void writeSourceOperand(int src) {
|
public void writeSourceOperand(int src) {
|
||||||
|
|
||||||
if (src < 0 || src > 31) {
|
if (src < 0 || src > 31) {
|
||||||
LogManager.LOGGER.severe("Couldn't write the scr operand for instruction :" + src);
|
LogManager.LOGGER.severe("Couldn't write the scr operand for instruction :" + src);
|
||||||
@ -62,7 +62,7 @@ class MachineCode {
|
|||||||
*
|
*
|
||||||
* @param dst signed 5-bit integer (value 0-31)
|
* @param dst signed 5-bit integer (value 0-31)
|
||||||
*/
|
*/
|
||||||
void writeDestinationOperand(int dst) {
|
public void writeDestinationOperand(int dst) {
|
||||||
if (dst < 0 || dst > 31) {
|
if (dst < 0 || dst > 31) {
|
||||||
LogManager.LOGGER.severe("Couldn't write the dst operand for instruction :" + dst);
|
LogManager.LOGGER.severe("Couldn't write the dst operand for instruction :" + dst);
|
||||||
} else {
|
} else {
|
||||||
@ -73,22 +73,20 @@ class MachineCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendWord(char word) {
|
public void appendWord(char word) {
|
||||||
additionalWords.add(word);
|
additionalWords.add(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the bytes of the code
|
* Get the bytes of the code
|
||||||
*/
|
*/
|
||||||
byte[] bytes() {
|
public byte[] bytes() {
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
|
||||||
out.write(value >> 8);
|
out.write(value >> 8);
|
||||||
out.write(value);
|
out.write(value);
|
||||||
|
|
||||||
|
|
||||||
for (Character s : additionalWords) {
|
for (Character s : additionalWords) {
|
||||||
out.write(s >> 8);
|
out.write(s >> 8);
|
||||||
out.write(s);
|
out.write(s);
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package net.simon987.server.assembly;
|
package net.simon987.server.assembly;
|
||||||
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import com.mongodb.DBObject;
|
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.io.MongoSerialisable;
|
import net.simon987.server.io.MongoSerializable;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -13,6 +12,7 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
import java.util.Random;
|
||||||
import java.util.zip.Deflater;
|
import java.util.zip.Deflater;
|
||||||
import java.util.zip.DeflaterOutputStream;
|
import java.util.zip.DeflaterOutputStream;
|
||||||
import java.util.zip.Inflater;
|
import java.util.zip.Inflater;
|
||||||
@ -21,7 +21,7 @@ import java.util.zip.InflaterOutputStream;
|
|||||||
/**
|
/**
|
||||||
* Represents the available memory for a CPU in the game universe
|
* Represents the available memory for a CPU in the game universe
|
||||||
*/
|
*/
|
||||||
public class Memory implements Target, MongoSerialisable {
|
public class Memory implements Target, MongoSerializable {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,6 +38,31 @@ public class Memory implements Target, MongoSerialisable {
|
|||||||
words = new char[size];
|
words = new char[size];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Memory(Document document) {
|
||||||
|
|
||||||
|
String zipBytesStr = (String) document.get("zipBytes");
|
||||||
|
|
||||||
|
if (zipBytesStr != null) {
|
||||||
|
byte[] compressedBytes = Base64.getDecoder().decode((String) document.get("zipBytes"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
Inflater decompressor = new Inflater(true);
|
||||||
|
InflaterOutputStream inflaterOutputStream = new InflaterOutputStream(baos, decompressor);
|
||||||
|
inflaterOutputStream.write(compressedBytes);
|
||||||
|
inflaterOutputStream.close();
|
||||||
|
|
||||||
|
setBytes(baos.toByteArray());
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LogManager.LOGGER.severe("Memory was manually deleted");
|
||||||
|
words = new char[GameServer.INSTANCE.getConfig().getInt("memory_size")];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value at an address
|
* Get the value at an address
|
||||||
*
|
*
|
||||||
@ -87,6 +112,32 @@ public class Memory implements Target, MongoSerialisable {
|
|||||||
words[address] = (char) value;
|
words[address] = (char) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configurably corrupt memory
|
||||||
|
*
|
||||||
|
* @param blockSize Block size (in words) in which to randomly flip one bit
|
||||||
|
*/
|
||||||
|
public void corrupt(int blockSize) {
|
||||||
|
Random rand = new Random();
|
||||||
|
|
||||||
|
// Increment offset by blockSize
|
||||||
|
for (int offset = 0; offset < words.length; offset += blockSize) {
|
||||||
|
|
||||||
|
// Calculate address to corrupt by adding a random value between 0 to (blocksize-1) to offset
|
||||||
|
int address = rand.nextInt(blockSize) + offset;
|
||||||
|
|
||||||
|
// Checking here avoids having a protected area at the end of the address space
|
||||||
|
if(address < words.length) {
|
||||||
|
|
||||||
|
// Calculate bitmask by left-shifting 1 by a random value between 0 and 15
|
||||||
|
int bitmask = 1 << rand.nextInt(16);
|
||||||
|
|
||||||
|
// Flip the bit with XOR
|
||||||
|
words[address] ^= bitmask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the memory with 0s
|
* Fill the memory with 0s
|
||||||
*/
|
*/
|
||||||
@ -106,9 +157,9 @@ public class Memory implements Target, MongoSerialisable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject mongoSerialise() {
|
public Document mongoSerialise() {
|
||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
Document dbObject = new Document();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
@ -127,35 +178,6 @@ public class Memory implements Target, MongoSerialisable {
|
|||||||
return dbObject;
|
return dbObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Memory deserialize(DBObject obj) {
|
|
||||||
|
|
||||||
Memory memory = new Memory(0);
|
|
||||||
|
|
||||||
String zipBytesStr = (String) obj.get("zipBytes");
|
|
||||||
|
|
||||||
if (zipBytesStr != null) {
|
|
||||||
byte[] compressedBytes = Base64.getDecoder().decode((String) obj.get("zipBytes"));
|
|
||||||
|
|
||||||
try {
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
Inflater decompressor = new Inflater(true);
|
|
||||||
InflaterOutputStream inflaterOutputStream = new InflaterOutputStream(baos, decompressor);
|
|
||||||
inflaterOutputStream.write(compressedBytes);
|
|
||||||
inflaterOutputStream.close();
|
|
||||||
|
|
||||||
memory.setBytes(baos.toByteArray());
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LogManager.LOGGER.severe("Memory was manually deleted");
|
|
||||||
memory = new Memory(GameServer.INSTANCE.getConfig().getInt("memory_size"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBytes(byte[] bytes) {
|
public void setBytes(byte[] bytes) {
|
||||||
this.words = new char[bytes.length / 2];
|
this.words = new char[bytes.length / 2];
|
||||||
ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).asCharBuffer().get(this.words);
|
ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).asCharBuffer().get(this.words);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user