mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-04-10 14:26:45 +00:00
Compare commits
406 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 | ||
|
a7d1a00ae8 | ||
|
95a14ad1ab | ||
|
8d961ce572 | ||
|
c772abe0bf | ||
|
187a828c79 | ||
|
ffca185fe5 | ||
|
815f3de234 | ||
|
3505a466bb | ||
|
3d10e4306b | ||
|
210e579995 | ||
|
a285b3104e | ||
|
947deea784 | ||
|
4293fc0315 | ||
|
33955d9639 | ||
|
6b91251b4e | ||
|
695341428a | ||
|
c610929809 | ||
|
54b72e89b3 | ||
|
59fd620e4a | ||
|
2fbc55d0dd | ||
|
e1dfb08635 | ||
|
f1c1f8f807 | ||
|
7cbfb822b8 | ||
|
a04207b5e0 | ||
|
6fc583d6f0 | ||
|
46483b2bf8 | ||
|
d65660b5e9 | ||
|
593be7624e | ||
|
a14853b12c | ||
|
735a231767 | ||
|
1131e4d512 | ||
|
cfb02869bb | ||
|
cde03af8af | ||
|
ff9370fed5 | ||
|
eaef30eb49 | ||
|
f68027bb4d | ||
|
24d81d194e | ||
|
c7b9df0690 | ||
|
a8beb8c3e2 | ||
|
0bd25df977 | ||
|
9bb0dc9034 | ||
|
8b0460f5f1 | ||
|
ce0584a49f | ||
|
0dc4ddca0f | ||
|
1da894959e | ||
|
7e773699b6 | ||
|
bc29c36204 | ||
|
811a443a4e | ||
|
17359161fd | ||
|
afbbce215e | ||
|
1a39cf8454 | ||
|
9bc3cbf4ce | ||
|
9b908a5310 | ||
|
8ceeca564a | ||
|
d4fcf22550 | ||
|
d25d42534a | ||
|
58a378d77f | ||
|
cfaf46ad52 | ||
|
eb3deba544 | ||
|
ba53212986 | ||
|
7bb5f68ff2 | ||
|
65ec6a2102 | ||
|
5a994fe437 | ||
|
415500faa9 | ||
|
3ded64cb16 | ||
|
1a0291d517 | ||
|
4e76d57ef9 | ||
|
c7da764505 | ||
|
2a5d6b5a13 | ||
|
e2763faeee | ||
|
2a8658c598 | ||
|
85548ec3cb | ||
|
0f7b40f3ae | ||
|
ee60216784 | ||
|
c3a0d1bd4d | ||
|
cd8d883134 | ||
|
c7946a6356 | ||
|
7ee361b0bc | ||
|
1e26c63358 | ||
|
d832f65535 | ||
|
e47e573b61 | ||
|
93786d92cb | ||
|
34178016b1 | ||
|
b31c187ad5 | ||
|
deb3859dff | ||
|
b21e33601e | ||
|
b2474494cc | ||
|
6b2e3c17ed | ||
|
079a63e39c | ||
|
347dc2bce0 | ||
|
90ad8e82eb | ||
|
04374e6e0a | ||
|
4a6ee4cce6 | ||
|
37e40d0329 | ||
|
99cefba245 | ||
|
7821d428e2 | ||
|
93bea49a3e | ||
|
cca68ba139 | ||
|
83f05efff6 | ||
|
ea3b06c54c | ||
|
1ed9e9e4db | ||
|
08f1aa8686 | ||
|
55d4c19fe1 | ||
|
2398219fab | ||
|
81767ed5cf | ||
|
2ef6f492c4 | ||
|
70a55dce59 | ||
|
fe0be03ab8 | ||
|
fd73a47796 | ||
|
eea9420192 | ||
|
9e402fe8a1 | ||
|
b3d88b2813 | ||
|
ef7f573256 | ||
|
5afa767b4a | ||
|
a9e580f2ce | ||
|
c4caf4ab0b | ||
|
0c06d0bf09 | ||
|
017b89f97f | ||
|
bd276e0a93 | ||
|
72d43fccf7 | ||
|
18aaf91991 | ||
|
bbcadbf253 | ||
|
3d60f9a67c | ||
|
b43cf9ac33 | ||
|
293795b215 | ||
|
fde79ed97e | ||
|
fcd339c315 | ||
|
59e3e9430e | ||
|
45ec7191b4 | ||
|
d9732557fc | ||
|
eced45a358 | ||
|
0fee35baec | ||
|
729debb1a3 | ||
|
2fb7d2f73e | ||
|
dab5cab602 | ||
|
c23ee0dc86 | ||
|
96cce8478e | ||
|
9d184cb515 | ||
|
09e00fd032 | ||
|
e1d0833c3a | ||
|
8a980fec6a | ||
|
e96b7982c8 | ||
|
21ec4ae704 | ||
|
690b7e8d31 | ||
|
d28ca387d0 | ||
|
f2b6387cc9 | ||
|
f3b20b3a2d | ||
|
f4fd3866eb | ||
|
965ca91cb6 | ||
|
556f443ec2 | ||
|
3158dd75ea | ||
|
1b6927c575 | ||
|
3bd34bfcba | ||
|
2e9248ea2e | ||
|
4f1342593f | ||
|
3548928218 | ||
|
cd41db9e58 | ||
|
597118bd07 | ||
|
9dd9b45d2d | ||
|
9597a80edf | ||
|
d24363fd82 | ||
|
be45979ed0 | ||
|
29cac77e79 | ||
|
6be2a496c6 | ||
|
12db25e726 | ||
|
d004386b7b | ||
|
e09d2c1b16 | ||
|
c703dec3cf | ||
|
8701007ad9 | ||
|
cfb8050cee | ||
|
da7d050661 | ||
|
3ee9b4be95 | ||
|
42421b7710 | ||
|
9979986c6a | ||
|
c5abe2efc5 | ||
|
fdfa568e07 | ||
|
1bf1682cb3 | ||
|
a3fa3c4c09 | ||
|
f7ea14275c | ||
|
04d51e1f1f | ||
|
8c5dcd0fba | ||
|
1a6f92a29d | ||
|
3d9bfb2a42 | ||
|
e2ed744479 |
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
|
22
.gitignore
vendored
Normal file
22
.gitignore
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
plugins/Plugin NPC.jar
|
||||
plugins/Plugin Misc HW.jar
|
||||
plugins/Plant.jar
|
||||
plugins/Cubot.jar
|
||||
.idea/*
|
||||
mar.log
|
||||
mar.log.lck
|
||||
*.iml
|
||||
*.class
|
||||
*/target/*
|
||||
plugins/*.jar
|
||||
save.json
|
||||
Server/Server.iml
|
||||
target/*
|
||||
Server/Server.iml
|
||||
Server/src/main/java/META-INF/MANIFEST.MF
|
||||
.settings
|
||||
.project
|
||||
.classpath
|
||||
# VSCode Workspace
|
||||
.vscode/
|
19
CONTRIBUTING.md
Normal file
19
CONTRIBUTING.md
Normal file
@ -0,0 +1,19 @@
|
||||
## General guide
|
||||
|
||||
[Collaboration guide](https://github.com/simon987/Much-Assembly-Required/wiki/Collaboration-Guide)
|
||||
|
||||
## Before creating a pull request
|
||||
|
||||
Here small unordered list of guidelines to read before creating a pull request
|
||||
- Use java <= 1.8 features
|
||||
- Please follow [Google's Java style guide](https://google.github.io/styleguide/javaguide.html)
|
||||
- Constants (e.g. the energy cost of an in-game action) should be loaded from config.properties
|
||||
- The project is separated into multiple modules, the `Server` module and its plugins. Plugins should
|
||||
not depend on another plugin to compile or to run.
|
||||
(e.g. NPC plugin shouldn't import `net.simon987.biomassplugin` )
|
||||
- Use `Logmanager.LOGGER` to log messages to the console. Use `.fine()` for debugging messages and `.info()` for
|
||||
info for more important messages
|
||||
that are not too frequently used.
|
||||
- Do not submit a pull request for a new feature that has not been approved
|
||||
by [simon987](https://github.com/simon987) in an Issue beforehand
|
||||
- Please state what tests have been performed in the pull request
|
6
Dockerfile
Normal file
6
Dockerfile
Normal file
@ -0,0 +1,6 @@
|
||||
FROM maven:3.5-jdk-8
|
||||
COPY /. /app/
|
||||
WORKDIR /app
|
||||
RUN mvn package
|
||||
WORKDIR /app/target
|
||||
CMD ["java", "-jar", "/app/target/server-1.4a.jar"]
|
674
LICENSE
Normal file
674
LICENSE
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
59
Plugin Cubot/Plugin Cubot.iml
Normal file
59
Plugin Cubot/Plugin Cubot.iml
Normal file
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
<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$/test" isTestSource="true" />
|
||||
<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="module" module-name="Server" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-sync:3.9.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mongodb:bson:3.9.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: junit:junit:4.10" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
||||
</component>
|
||||
</module>
|
34
Plugin Cubot/pom.xml
Normal file
34
Plugin Cubot/pom.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?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.plugincubot</groupId>
|
||||
<artifactId>plugin-cubot</artifactId>
|
||||
<version>1.4a</version>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.simon987.server</groupId>
|
||||
<artifactId>server</artifactId>
|
||||
<version>1.4a</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
<artifactId>json-simple</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
605
Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java
Normal file
605
Plugin Cubot/src/main/java/net/simon987/cubotplugin/Cubot.java
Normal file
@ -0,0 +1,605 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.cubotplugin.event.CubotWalkEvent;
|
||||
import net.simon987.cubotplugin.event.DeathEvent;
|
||||
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.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 org.bson.Document;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class Cubot extends GameObject implements Updatable, ControllableUnit, MessageReceiver {
|
||||
|
||||
private static final char MAP_INFO = 0x0200;
|
||||
|
||||
/**
|
||||
* Hit points
|
||||
*/
|
||||
private int hp;
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Action at the end of the last tick
|
||||
*/
|
||||
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<>();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* Console mode that was set during the current tick. It is set to NORMAL by default
|
||||
*/
|
||||
private ConsoleMode consoleMode = ConsoleMode.NORMAL;
|
||||
/**
|
||||
* Console mode at the end of the last tick
|
||||
*/
|
||||
private ConsoleMode lastConsoleMode = ConsoleMode.NORMAL;
|
||||
|
||||
/**
|
||||
* User that controls this Cubot
|
||||
*/
|
||||
private User parent;
|
||||
|
||||
/**
|
||||
* Maximum size of the console buffer (also called 'internal buffer')
|
||||
*/
|
||||
public 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(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
|
||||
public char getMapInfo() {
|
||||
return MAP_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
if (currentAction == Action.WALKING) {
|
||||
if (spendEnergy(100)) {
|
||||
if (!incrementLocation()) {
|
||||
//Couldn't walk
|
||||
currentAction = Action.IDLE;
|
||||
}else{
|
||||
GameServer.INSTANCE.getEventDispatcher().dispatch(new CubotWalkEvent(this));
|
||||
}
|
||||
} else {
|
||||
currentAction = Action.IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CurrentAction is set during the code execution and this function is called right after
|
||||
* If no action as been set, the action sent to the client is the action in currentAction that
|
||||
* was set last tick (IDLE)
|
||||
*/
|
||||
lastAction = currentAction;
|
||||
currentAction = Action.IDLE;
|
||||
|
||||
//Same principle for hologram
|
||||
|
||||
//And the console
|
||||
lastConsoleMode = consoleMode;
|
||||
consoleMode = ConsoleMode.NORMAL;
|
||||
|
||||
lastConsoleMessagesBuffer = new ArrayList<>(consoleMessagesBuffer);
|
||||
consoleMessagesBuffer.clear();
|
||||
|
||||
//And the status..
|
||||
lastStatus = currentStatus;
|
||||
currentStatus = 0;
|
||||
|
||||
for (HardwareModule module : hardwareAddresses.values()) {
|
||||
module.update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject jsonSerialise() {
|
||||
JSONObject json = super.jsonSerialise();
|
||||
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("hp", hp);
|
||||
json.put("shield", shield);
|
||||
json.put("action", lastAction.ordinal());
|
||||
|
||||
if (parent != null) {
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
Document dbObject = super.mongoSerialise();
|
||||
|
||||
dbObject.put("direction", getDirection().ordinal());
|
||||
dbObject.put("hp", hp);
|
||||
dbObject.put("shield", shield);
|
||||
dbObject.put("action", lastAction.ordinal());
|
||||
|
||||
if (parent != null) {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset to 'factory settings', as it were when it was first created
|
||||
*/
|
||||
private void reset() {
|
||||
setDead(false);
|
||||
setHp(maxHp);
|
||||
setShield(0);
|
||||
setEnergy(((CubotBattery) getHardware(CubotBattery.class)).getMaxEnergy());
|
||||
clearKeyboardBuffer();
|
||||
consoleMessagesBuffer.clear();
|
||||
lastConsoleMessagesBuffer.clear();
|
||||
currentStatus = 0;
|
||||
lastStatus = 0;
|
||||
addStatus(CubotStatus.FACTORY_NEW);
|
||||
|
||||
for (HardwareModule module : hardwareAddresses.values()) {
|
||||
module.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDeadCallback() {
|
||||
GameEvent event = new DeathEvent(this);
|
||||
GameServer.INSTANCE.getEventDispatcher().dispatch(event);
|
||||
|
||||
reset();
|
||||
|
||||
//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
|
||||
public void setKeyboardBuffer(ArrayList<Integer> kbBuffer) {
|
||||
keyboardBuffer = kbBuffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Integer> getKeyboardBuffer() {
|
||||
return keyboardBuffer;
|
||||
}
|
||||
|
||||
public void clearKeyboardBuffer() {
|
||||
keyboardBuffer.clear();
|
||||
}
|
||||
|
||||
public void setCurrentAction(Action currentAction) {
|
||||
this.currentAction = currentAction;
|
||||
}
|
||||
|
||||
public void setParent(User parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public Action getAction() {
|
||||
return lastAction;
|
||||
}
|
||||
|
||||
public Action getCurrentAction() {
|
||||
return currentAction;
|
||||
}
|
||||
|
||||
public int getEnergy() {
|
||||
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||
return battery.getEnergy();
|
||||
}
|
||||
|
||||
public void setEnergy(int energy) {
|
||||
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||
battery.setEnergy(energy);
|
||||
}
|
||||
|
||||
public boolean spendEnergy(int amount) {
|
||||
|
||||
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||
|
||||
if (battery.getEnergy() - amount < 0) {
|
||||
return false;
|
||||
} else {
|
||||
battery.setEnergy(battery.getEnergy() - amount);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void storeEnergy(int amount) {
|
||||
|
||||
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||
battery.setEnergy(Math.min(battery.getEnergy() + amount, battery.getMaxEnergy()));
|
||||
}
|
||||
|
||||
public void setMaxEnergy(int maxEnergy) {
|
||||
CubotBattery battery = (CubotBattery) getHardware(CubotBattery.class);
|
||||
battery.setMaxEnergy(maxEnergy);
|
||||
}
|
||||
|
||||
public int getMaxEnergy() {
|
||||
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
|
||||
public Memory getFloppyData() {
|
||||
|
||||
CubotFloppyDrive drive = (CubotFloppyDrive) getHardware(CubotFloppyDrive.class);
|
||||
|
||||
if (drive.getFloppy() != null) {
|
||||
return drive.getFloppy().getMemory();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAt(int x, int y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAction(Action action) {
|
||||
currentAction = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendMessage(char[] message) {
|
||||
|
||||
if (consoleMessagesBuffer.size() < CONSOLE_BUFFER_MAX_SIZE) {
|
||||
consoleMessagesBuffer.add(message);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<char[]> getConsoleMessagesBuffer() {
|
||||
return lastConsoleMessagesBuffer;
|
||||
}
|
||||
|
||||
|
||||
public int getConsoleMode() {
|
||||
return lastConsoleMode.ordinal();
|
||||
}
|
||||
|
||||
public void setConsoleMode(ConsoleMode consoleMode) {
|
||||
this.consoleMode = consoleMode;
|
||||
}
|
||||
|
||||
public void addStatus(CubotStatus status) {
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
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 CubotBattery extends HardwareModule {
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 0x000A;
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
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 static final int BATTERY_POLL = 1;
|
||||
private static final int BATTERY_GET_MAX_CAPACITY = 2;
|
||||
|
||||
public CubotBattery(ControllableUnit unit) {
|
||||
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
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
if (a == BATTERY_POLL) {
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(energy);
|
||||
|
||||
} else if (a == BATTERY_GET_MAX_CAPACITY) {
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(maxEnergy);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
energy = Math.min(maxEnergy,
|
||||
energy + (int) (SOLAR_PANEL_MULTIPLIER * GameServer.INSTANCE.getDayNightCycle().getSunIntensity()));
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.assembly.HardwareModule;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.objects.ControllableUnit;
|
||||
import net.simon987.server.game.objects.GameObject;
|
||||
import net.simon987.server.game.objects.MessageReceiver;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CubotComPort extends HardwareModule {
|
||||
|
||||
public static final char HWID = 0xD;
|
||||
public static final int DEFAULT_ADDRESS = 0xD;
|
||||
|
||||
private static final int COMPORT_BUFFER_CLEAR = 0;
|
||||
private static final int COMPORT_POLL = 1;
|
||||
private static final int COMPORT_FRONT_PORT_OUT = 2;
|
||||
private static final int COMPORT_SELF_OUT = 3;
|
||||
private static final int COMPORT_CONSOLE_CLEAR = 4;
|
||||
|
||||
public CubotComPort(ControllableUnit unit) {
|
||||
super(null, unit);
|
||||
}
|
||||
|
||||
public CubotComPort(Document document, ControllableUnit cubot) {
|
||||
super(document, cubot);
|
||||
}
|
||||
|
||||
private static final int MESSAGE_LENGTH = 8;
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
if (a == COMPORT_BUFFER_CLEAR) {
|
||||
|
||||
unit.getConsoleMessagesBuffer().clear();
|
||||
|
||||
} else if (a == COMPORT_CONSOLE_CLEAR) {
|
||||
|
||||
if (unit instanceof Cubot) {
|
||||
((Cubot) unit).setConsoleMode(Cubot.ConsoleMode.CLEAR);
|
||||
}
|
||||
|
||||
} else if (a == COMPORT_POLL) {
|
||||
|
||||
if (unit.spendEnergy(4)) {
|
||||
|
||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||
|
||||
//Read all messages in the console buffer to memory at X
|
||||
|
||||
for (char[] message : unit.getConsoleMessagesBuffer()) {
|
||||
if (x + MESSAGE_LENGTH >= getCpu().getMemory().getWords().length) {
|
||||
//todo set interrupt ?
|
||||
getCpu().getStatus().setErrorFlag(true);
|
||||
} else {
|
||||
System.arraycopy(message, 0, getCpu().getMemory().getWords(), x, MESSAGE_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
//Set B = number of messages
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(unit.getConsoleMessagesBuffer().size());
|
||||
|
||||
}
|
||||
|
||||
} else if (a == COMPORT_FRONT_PORT_OUT) {
|
||||
|
||||
if (unit.spendEnergy(5)) {
|
||||
//Get object directly in front of the Cubot
|
||||
Point frontTile = unit.getFrontTile();
|
||||
//Todo will have to add getGameObjectsBlockingAt to enable Factory
|
||||
ArrayList<GameObject> objects = unit.getWorld().getGameObjectsAt(frontTile.x, frontTile.y);
|
||||
|
||||
if (objects.size() > 0 && objects.get(0) instanceof MessageReceiver) {
|
||||
|
||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||
|
||||
if (x + MESSAGE_LENGTH >= getCpu().getMemory().getWords().length) {
|
||||
//todo set interrupt ?
|
||||
getCpu().getStatus().setErrorFlag(true);
|
||||
} else {
|
||||
|
||||
//Get MESSAGE_LENGTH-word message pointed by X
|
||||
char[] message = new char[MESSAGE_LENGTH];
|
||||
System.arraycopy(getCpu().getMemory().getWords(), x, message, 0, MESSAGE_LENGTH);
|
||||
|
||||
//Send it to the MessageReceiver object
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(
|
||||
((MessageReceiver) objects.get(0)).sendMessage(message) ? 1 : 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(0); //Failed
|
||||
|
||||
} else if (a == COMPORT_SELF_OUT) {
|
||||
|
||||
if (unit.spendEnergy(1)) {
|
||||
|
||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||
|
||||
//Write a single message to console buffer
|
||||
if (x + MESSAGE_LENGTH >= getCpu().getMemory().getWords().length) {
|
||||
//todo set interrupt ?
|
||||
getCpu().getStatus().setErrorFlag(true);
|
||||
} else {
|
||||
|
||||
//Get MESSAGE_LENGTH-word message pointed by X
|
||||
char[] message = new char[MESSAGE_LENGTH];
|
||||
System.arraycopy(getCpu().getMemory().getWords(), x, message, 0, MESSAGE_LENGTH);
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(unit.sendMessage(message) ? 1 : 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(0); //Failed
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
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.Action;
|
||||
import net.simon987.server.game.objects.ControllableUnit;
|
||||
import net.simon987.server.game.world.Tile;
|
||||
import org.bson.Document;
|
||||
|
||||
public class CubotDrill extends HardwareModule {
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
static final char HWID = 0x0005;
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 5;
|
||||
|
||||
private static final int DRILL_POLL = 1;
|
||||
private static final int DRILL_GATHER = 2; // simplified gather
|
||||
|
||||
public CubotDrill(ControllableUnit unit) {
|
||||
super(null, unit);
|
||||
}
|
||||
|
||||
public CubotDrill(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();
|
||||
|
||||
if (a == DRILL_POLL) {
|
||||
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(0);
|
||||
|
||||
} else if (a == DRILL_GATHER) {
|
||||
|
||||
if (unit.spendEnergy(1400)) {
|
||||
if (unit.getCurrentAction() == Action.IDLE) {
|
||||
|
||||
Tile tile = unit.getWorld().getTileMap().getTileAt(unit.getX(), unit.getY());
|
||||
|
||||
Item newItem = tile.drill();
|
||||
if (newItem != null) {
|
||||
unit.setCurrentAction(Action.DIGGING);
|
||||
unit.giveItem(newItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.objects.ControllableUnit;
|
||||
import org.bson.Document;
|
||||
|
||||
public class CubotFloppyDrive extends CubotHardwareModule {
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
static final char HWID = 0x000B;
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 0x000B;
|
||||
|
||||
private static final int FLOPPY_POLL = 1;
|
||||
private static final int FLOPPY_READ_SECTOR = 2;
|
||||
private static final int FLOPPY_WRITE_SECTOR = 3;
|
||||
|
||||
private FloppyDisk floppyDisk;
|
||||
|
||||
public CubotFloppyDrive(Cubot cubot) {
|
||||
super(cubot);
|
||||
|
||||
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
|
||||
public void handleInterrupt(Status status) {
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
if (a == FLOPPY_POLL) {
|
||||
|
||||
if (floppyDisk != null) {
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(0);
|
||||
} else {
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(1);
|
||||
}
|
||||
|
||||
} else if (a == FLOPPY_READ_SECTOR) {
|
||||
|
||||
if (floppyDisk == null) {
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(0);
|
||||
} else {
|
||||
if (cubot.spendEnergy(1)) {
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(1);
|
||||
|
||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||
int y = getCpu().getRegisterSet().getRegister("Y").getValue();
|
||||
|
||||
floppyDisk.readSector(x, cubot.getCpu().getMemory(), y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if (a == FLOPPY_WRITE_SECTOR) {
|
||||
if (floppyDisk == null) {
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(0);
|
||||
} else {
|
||||
if (cubot.spendEnergy(1)) {
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(1);
|
||||
|
||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||
int y = getCpu().getRegisterSet().getRegister("Y").getValue();
|
||||
|
||||
floppyDisk.writeSector(x, cubot.getCpu().getMemory(), y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
|
||||
public FloppyDisk getFloppy() {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
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;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class CubotHologram extends HardwareModule {
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
static final char HWID = 0x0009;
|
||||
public static final int DEFAULT_ADDRESS = 9;
|
||||
|
||||
private static final int HOLO_CLEAR = 0;
|
||||
private static final int HOLO_DISPLAY_HEX = 1;
|
||||
private static final int HOLO_DISPLAY_STRING = 2;
|
||||
private static final int HOLO_DISPLAY_DEC = 3;
|
||||
private static final int HOLO_DISPLAY_COLOR = 4;
|
||||
|
||||
private static final int STR_MAX_LEN = 8;
|
||||
|
||||
private int displayValue = 0;
|
||||
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
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
char a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
if (a == HOLO_CLEAR) {
|
||||
mode = HologramMode.CLEARED;
|
||||
} else if (a == HOLO_DISPLAY_HEX) {
|
||||
displayValue = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||
mode = HologramMode.HEX;
|
||||
} else if (a == HOLO_DISPLAY_STRING) {
|
||||
char x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||
//Display zero-terminated string starting at X (max 8 chars)
|
||||
|
||||
StringBuilder holoString = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < STR_MAX_LEN; i++) {
|
||||
|
||||
char nextChar = (char) getCpu().getMemory().get(x + i);
|
||||
|
||||
if (nextChar != 0) {
|
||||
holoString.append((char) getCpu().getMemory().get(x + i));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
displayString = holoString.toString();
|
||||
mode = HologramMode.STRING;
|
||||
} else if (a == HOLO_DISPLAY_DEC) {
|
||||
//Display decimal number
|
||||
displayValue = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||
mode = HologramMode.DEC;
|
||||
|
||||
} else if (a == HOLO_DISPLAY_COLOR) {
|
||||
|
||||
if (unit.spendEnergy(4)) {
|
||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||
int c = getCpu().getRegisterSet().getRegister("C").getValue();
|
||||
|
||||
displayColor = (c | (b << 16)); //B:C
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
public JSONObject debugJsonSerialise() {
|
||||
JSONObject json = jsonSerialise();
|
||||
|
||||
json.put("lastmode", mode);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
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;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CubotInventory extends HardwareModule {
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
static final char HWID = 0x0006;
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 6;
|
||||
|
||||
private static final int INV_CLEAR = 0;
|
||||
private static final int INV_POLL = 1;
|
||||
private static final int INV_SEEK = 2;
|
||||
private static final int INV_SCAN = 3;
|
||||
|
||||
private int inventorySize = 4; //TODO: load from config
|
||||
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
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
if (a == INV_POLL) {
|
||||
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) {
|
||||
if (unit.spendEnergy(100)) {
|
||||
clearItem();
|
||||
}
|
||||
} else if (a == INV_SEEK) {
|
||||
setPosition(getCpu().getRegisterSet().getRegister("X").getValue());
|
||||
} else if (a == INV_SCAN) {
|
||||
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
|
||||
public String toString() {
|
||||
String itemList = "";
|
||||
for (Integer i : inventory.keySet()) {
|
||||
itemList += i + ": " + inventory.get(i).getClass().getSimpleName() + ", ";
|
||||
}
|
||||
return String.format("{CubotInventory[%d/%d] @ %d [%s]}", inventory.size(), inventorySize, position, itemList);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.objects.ControllableUnit;
|
||||
import org.bson.Document;
|
||||
|
||||
public class CubotKeyboard extends CubotHardwareModule {
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 4;
|
||||
|
||||
private static final int KEYBOARD_CLEAR_BUFFER = 0;
|
||||
private static final int KEYBOARD_FETCH_KEY = 1;
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
public static final char HWID = 0x0004;
|
||||
|
||||
public CubotKeyboard(Cubot cubot) {
|
||||
super(cubot);
|
||||
}
|
||||
|
||||
public CubotKeyboard(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();
|
||||
|
||||
if (a == KEYBOARD_CLEAR_BUFFER) {
|
||||
|
||||
cubot.clearKeyboardBuffer();
|
||||
|
||||
} else if (a == KEYBOARD_FETCH_KEY) {
|
||||
//pop
|
||||
int key = 0;
|
||||
if (cubot.getKeyboardBuffer().size() > 0) {
|
||||
key = cubot.getKeyboardBuffer().get(0);
|
||||
cubot.getKeyboardBuffer().remove(0);
|
||||
}
|
||||
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(key);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.assembly.HardwareModule;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.objects.*;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CubotLaser extends HardwareModule {
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
static final char HWID = 0x0002;
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 2;
|
||||
|
||||
private static final int LASER_WITHDRAW = 1;
|
||||
private static final int LASER_DEPOSIT = 2;
|
||||
private static final int LASER_ATTACK = 3;
|
||||
|
||||
private static final int LASER_DAMAGE = 25;
|
||||
|
||||
public CubotLaser(ControllableUnit unit) {
|
||||
super(null, unit);
|
||||
}
|
||||
|
||||
public CubotLaser(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();
|
||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||
|
||||
|
||||
if (a == LASER_WITHDRAW) {
|
||||
|
||||
|
||||
Point frontTile = unit.getFrontTile();
|
||||
ArrayList<GameObject> objects = unit.getWorld().getGameObjectsBlockingAt(frontTile.x, frontTile.y);
|
||||
|
||||
if (unit.getCurrentAction() == Action.IDLE && objects.size() > 0) {
|
||||
//FIXME: Problem here if more than 1 object
|
||||
if (objects.get(0) instanceof InventoryHolder) {
|
||||
|
||||
if (((InventoryHolder) objects.get(0)).canTakeItem(b)) {
|
||||
if (unit.spendEnergy(30)) {
|
||||
//Take the item
|
||||
((InventoryHolder) objects.get(0)).takeItem(b);
|
||||
unit.giveItem(GameServer.INSTANCE.getRegistry().makeItem(b));
|
||||
unit.setCurrentAction(Action.WITHDRAWING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if (a == LASER_DEPOSIT) {
|
||||
// TODO
|
||||
} else if (a == LASER_ATTACK) {
|
||||
|
||||
if (unit.getCurrentAction() == Action.IDLE) {
|
||||
if (unit.spendEnergy(70)) {
|
||||
|
||||
//Get object directly in front of the Cubot
|
||||
Point frontTile = unit.getFrontTile();
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unit.setCurrentAction(Action.ATTACKING);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.assembly.HardwareModule;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.objects.Action;
|
||||
import net.simon987.server.game.objects.ControllableUnit;
|
||||
import net.simon987.server.game.objects.Direction;
|
||||
import org.bson.Document;
|
||||
|
||||
public class CubotLeg extends HardwareModule {
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 1;
|
||||
|
||||
private static final int LEGS_SET_DIR = 1;
|
||||
private static final int LEGS_SET_DIR_AND_WALK = 2;
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
static final char HWID = 0x0001;
|
||||
|
||||
public CubotLeg(ControllableUnit unit) {
|
||||
super(null, unit);
|
||||
}
|
||||
|
||||
public CubotLeg(Document document, ControllableUnit unit) {
|
||||
super(document, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
if (unit.getCurrentAction() == Action.IDLE) {
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||
|
||||
if (a == LEGS_SET_DIR) {
|
||||
|
||||
|
||||
Direction dir = Direction.getDirection(b);
|
||||
|
||||
if (dir != null) {
|
||||
if (unit.spendEnergy(20)) {
|
||||
unit.setDirection(Direction.getDirection(b));
|
||||
status.setErrorFlag(false);
|
||||
}
|
||||
} else {
|
||||
status.setErrorFlag(true);
|
||||
}
|
||||
|
||||
|
||||
} else if (a == LEGS_SET_DIR_AND_WALK) {
|
||||
|
||||
if (unit.getMaxEnergy() >= 100) {
|
||||
Direction dir = Direction.getDirection(b);
|
||||
|
||||
if (dir != null) {
|
||||
unit.setDirection(Direction.getDirection(b));
|
||||
status.setErrorFlag(false);
|
||||
} else {
|
||||
status.setErrorFlag(true);
|
||||
}
|
||||
|
||||
unit.setCurrentAction(Action.WALKING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.assembly.HardwareModule;
|
||||
import net.simon987.server.assembly.Memory;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.objects.ControllableUnit;
|
||||
import net.simon987.server.game.pathfinding.Node;
|
||||
import net.simon987.server.game.pathfinding.Pathfinder;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CubotLidar extends HardwareModule {
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
public static final char HWID = 0x0003;
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 3;
|
||||
|
||||
private static final int LIDAR_GET_POS = 1;
|
||||
private static final int LIDAR_GET_PATH = 2;
|
||||
private static final int LIDAR_GET_MAP = 3;
|
||||
private static final int LIDAR_GET_WORLD_POS = 4;
|
||||
private static final int LIDAR_GET_WORLD_SIZE = 5;
|
||||
|
||||
public CubotLidar(ControllableUnit unit) {
|
||||
super(null, unit);
|
||||
}
|
||||
|
||||
public CubotLidar(Document document, ControllableUnit unit) {
|
||||
super(document, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
switch (a) {
|
||||
case LIDAR_GET_POS:
|
||||
getCpu().getRegisterSet().getRegister("X").setValue(unit.getX());
|
||||
getCpu().getRegisterSet().getRegister("Y").setValue(unit.getY());
|
||||
break;
|
||||
case LIDAR_GET_PATH:
|
||||
if (unit.spendEnergy(50)) {
|
||||
int c = getCpu().getRegisterSet().getRegister("C").getValue();
|
||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||
int destX = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||
int destY = getCpu().getRegisterSet().getRegister("Y").getValue();
|
||||
|
||||
//Get path
|
||||
ArrayList<Node> nodes = Pathfinder.findPath(unit.getWorld(), unit.getX(), unit.getY(),
|
||||
destX, destY, b);
|
||||
|
||||
//Write to memory
|
||||
Memory mem = getCpu().getMemory();
|
||||
|
||||
int counter = c;
|
||||
|
||||
if (nodes != null) {
|
||||
|
||||
Node lastNode = null;
|
||||
|
||||
for (Node n : nodes) {
|
||||
//Store the path as a sequence of directions
|
||||
if (lastNode == null) {
|
||||
lastNode = n;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n.x < lastNode.x) {
|
||||
//West
|
||||
mem.set(counter++, 3);
|
||||
} else if (n.x > lastNode.x) {
|
||||
//East
|
||||
mem.set(counter++, 1);
|
||||
} else if (n.y < lastNode.y) {
|
||||
//North
|
||||
mem.set(counter++, 0);
|
||||
} else if (n.y > lastNode.y) {
|
||||
//South
|
||||
mem.set(counter++, 2);
|
||||
}
|
||||
|
||||
lastNode = n;
|
||||
}
|
||||
|
||||
//Indicate end of path with 0xAAAA
|
||||
mem.set(counter, 0xAAAA);
|
||||
} else {
|
||||
//Indicate invalid path 0xFFFF
|
||||
mem.set(counter, 0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LIDAR_GET_MAP:
|
||||
if (unit.spendEnergy(10)) {
|
||||
char[][] mapInfo = unit.getWorld().getMapInfo();
|
||||
|
||||
//Write map data to the location specified by register X
|
||||
int i = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LIDAR_GET_WORLD_SIZE:
|
||||
getCpu().getRegisterSet().getRegister("X").setValue(unit.getWorld().getWorldSize());
|
||||
getCpu().getRegisterSet().getRegister("Y").setValue(unit.getWorld().getWorldSize());
|
||||
break;
|
||||
|
||||
case LIDAR_GET_WORLD_POS:
|
||||
getCpu().getRegisterSet().getRegister("X").setValue(unit.getWorld().getX());
|
||||
getCpu().getRegisterSet().getRegister("Y").setValue(unit.getWorld().getY());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.cubotplugin.event.*;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.game.objects.GameRegistry;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.plugin.ServerPlugin;
|
||||
|
||||
public class CubotPlugin extends ServerPlugin {
|
||||
|
||||
|
||||
@Override
|
||||
public void init(GameServer gameServer) {
|
||||
listeners.add(new CpuInitialisationListener());
|
||||
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());
|
||||
|
||||
GameRegistry registry = gameServer.getRegistry();
|
||||
|
||||
registry.registerGameObject(Cubot.class);
|
||||
|
||||
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);
|
||||
|
||||
LogManager.LOGGER.info("(Cubot Plugin) Initialised Cubot plugin");
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
|
||||
import net.simon987.server.assembly.Memory;
|
||||
import net.simon987.server.io.MongoSerializable;
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* Represents a floppy disk that is inside a floppy drive.
|
||||
* 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)
|
||||
*/
|
||||
public class FloppyDisk implements MongoSerializable {
|
||||
|
||||
/**
|
||||
* Contents of the disk
|
||||
*/
|
||||
private Memory memory;
|
||||
|
||||
/**
|
||||
* Current location of the read/write head.
|
||||
* Used to calculate seek time
|
||||
*/
|
||||
private int rwHeadTrack = 0;
|
||||
|
||||
|
||||
public FloppyDisk() {
|
||||
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
|
||||
*
|
||||
* @param sector sector to read (0-1440)
|
||||
* @param cpuMemory Cpu memory to write to
|
||||
* @param ramAddress address of the data to write in CPU memory
|
||||
* @return Whether or not the read operation was in the same track as the last r/w
|
||||
*/
|
||||
public boolean readSector(int sector, Memory cpuMemory, int ramAddress) {
|
||||
|
||||
if (sector <= 1440) {
|
||||
cpuMemory.write(ramAddress, memory.getWords(), sector * 512, 512);
|
||||
|
||||
//Calculate seek time
|
||||
int deltaTrack = (sector / 80) - rwHeadTrack;
|
||||
|
||||
if (deltaTrack != 0) {
|
||||
rwHeadTrack = (sector / 80);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 512 words to the specified sector from cpu memory at the specified address
|
||||
*
|
||||
* @param sector sector to write (0-1440)
|
||||
* @param cpuMemory Cpu memory to read from
|
||||
* @param ramAddress address of the data to read in CPU memory
|
||||
* @return Whether or not the read operation was in the same track as the last r/w
|
||||
*/
|
||||
public boolean writeSector(int sector, Memory cpuMemory, int ramAddress) {
|
||||
|
||||
if (sector <= 1440) {
|
||||
memory.write(sector * 512, cpuMemory.getWords(), ramAddress, 512);
|
||||
|
||||
//Calculate seek time
|
||||
int deltaTrack = (sector / 80) - rwHeadTrack;
|
||||
|
||||
if (deltaTrack != 0) {
|
||||
rwHeadTrack = (sector / 80);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
Document dbObject = new Document();
|
||||
|
||||
dbObject.put("rwHeadTrack", rwHeadTrack);
|
||||
dbObject.put("memory", memory.mongoSerialise());
|
||||
|
||||
return dbObject;
|
||||
}
|
||||
|
||||
public Memory getMemory() {
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package net.simon987.cubotplugin.event;
|
||||
|
||||
import net.simon987.cubotplugin.*;
|
||||
import net.simon987.server.assembly.CPU;
|
||||
import net.simon987.server.event.CpuInitialisationEvent;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.event.GameEventListener;
|
||||
|
||||
public class CpuInitialisationListener implements GameEventListener {
|
||||
@Override
|
||||
public Class getListenedEventType() {
|
||||
return CpuInitialisationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(GameEvent event) {
|
||||
|
||||
CPU cpu = (CPU) event.getSource();
|
||||
Cubot cubot = (Cubot) ((CpuInitialisationEvent) event).getUnit();
|
||||
cpu.setHardwareHost(cubot);
|
||||
|
||||
CubotLeg legHw = new CubotLeg(cubot);
|
||||
legHw.setCpu(cpu);
|
||||
CubotLaser laserHw = new CubotLaser(cubot);
|
||||
laserHw.setCpu(cpu);
|
||||
CubotLidar radarHw = new CubotLidar(cubot);
|
||||
radarHw.setCpu(cpu);
|
||||
CubotKeyboard keyboard = new CubotKeyboard(cubot);
|
||||
keyboard.setCpu(cpu);
|
||||
CubotDrill drillHw = new CubotDrill(cubot);
|
||||
drillHw.setCpu(cpu);
|
||||
CubotInventory invHw = new CubotInventory(cubot);
|
||||
invHw.setCpu(cpu);
|
||||
CubotHologram emoteHw = new CubotHologram(cubot);
|
||||
emoteHw.setCpu(cpu);
|
||||
CubotBattery batteryHw = new CubotBattery(cubot);
|
||||
batteryHw.setCpu(cpu);
|
||||
CubotFloppyDrive floppyHw = new CubotFloppyDrive(cubot);
|
||||
floppyHw.setCpu(cpu);
|
||||
CubotComPort comPortHw = new CubotComPort(cubot);
|
||||
comPortHw.setCpu(cpu);
|
||||
CubotCore coreHw = new CubotCore(cubot);
|
||||
coreHw.setCpu(cpu);
|
||||
CubotShield shieldHw = new CubotShield(cubot);
|
||||
shieldHw.setCpu(cpu);
|
||||
|
||||
cubot.attachHardware(legHw, CubotLeg.DEFAULT_ADDRESS);
|
||||
cubot.attachHardware(laserHw, CubotLaser.DEFAULT_ADDRESS);
|
||||
cubot.attachHardware(radarHw, CubotLidar.DEFAULT_ADDRESS);
|
||||
cubot.attachHardware(keyboard, CubotKeyboard.DEFAULT_ADDRESS);
|
||||
cubot.attachHardware(drillHw, CubotDrill.DEFAULT_ADDRESS);
|
||||
cubot.attachHardware(invHw, CubotInventory.DEFAULT_ADDRESS);
|
||||
cubot.attachHardware(invHw, CubotInventory.DEFAULT_ADDRESS);
|
||||
cubot.attachHardware(emoteHw, CubotHologram.DEFAULT_ADDRESS);
|
||||
cubot.attachHardware(batteryHw, CubotBattery.DEFAULT_ADDRESS);
|
||||
cubot.attachHardware(floppyHw, CubotFloppyDrive.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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package net.simon987.cubotplugin.event;
|
||||
|
||||
import net.simon987.cubotplugin.Cubot;
|
||||
import net.simon987.cubotplugin.CubotStatus;
|
||||
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.GameEventListener;
|
||||
import net.simon987.server.event.UserCreationEvent;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.user.User;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Random;
|
||||
|
||||
public class UserCreationListener implements GameEventListener {
|
||||
@Override
|
||||
public Class getListenedEventType() {
|
||||
return UserCreationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(GameEvent event) {
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
User user = (User) event.getSource();
|
||||
Cubot cubot = new Cubot();
|
||||
cubot.addStatus(CubotStatus.FACTORY_NEW);
|
||||
cubot.setObjectId(new ObjectId());
|
||||
IServerConfiguration config = GameServer.INSTANCE.getConfig();
|
||||
|
||||
Point point = null;
|
||||
while (point == null || cubot.getWorld() == null) {
|
||||
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");
|
||||
cubot.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(spawnX, spawnY, true, dimension));
|
||||
|
||||
point = cubot.getWorld().getRandomPassableTile();
|
||||
}
|
||||
|
||||
cubot.setX(point.x);
|
||||
cubot.setY(point.y);
|
||||
cubot.getWorld().addObject(cubot);
|
||||
cubot.getWorld().incUpdatable();
|
||||
|
||||
cubot.setParent(user);
|
||||
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)");
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.game.*;
|
||||
import net.simon987.server.user.User;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Cubot extends GameObject implements Updatable, ControllableUnit {
|
||||
|
||||
private static final char MAP_INFO = 0x0080;
|
||||
public static final int ID = 1;
|
||||
|
||||
private EffectType currentEmote = null;
|
||||
|
||||
/**
|
||||
* Hit points
|
||||
*/
|
||||
private int hp;
|
||||
private int heldItem;
|
||||
|
||||
private CubotAction currentAction = CubotAction.IDLE;
|
||||
private CubotAction lastAction = CubotAction.IDLE;
|
||||
|
||||
private ArrayList<Integer> keyboardBuffer = new ArrayList<>();
|
||||
|
||||
private User parent;
|
||||
|
||||
public Cubot() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getMapInfo() {
|
||||
return MAP_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
|
||||
if (currentAction == CubotAction.WALKING) {
|
||||
if (!incrementLocation()) {
|
||||
//Couldn't walk
|
||||
currentAction = CubotAction.IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentEmote != null) {
|
||||
// getWorld().getQueuedGameEffects().add(new GameEffect(currentEmote, getX(), getY()));
|
||||
currentEmote = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* CurrentAction is set during the code execution and this function is called right after
|
||||
* If no action as been set, the action sent to the client is the action in currentAction that
|
||||
* was set last tick (IDLE)
|
||||
*/
|
||||
lastAction = currentAction;
|
||||
currentAction = CubotAction.IDLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("id", getObjectId());
|
||||
json.put("type", ID);
|
||||
json.put("x", getX());
|
||||
json.put("y", getY());
|
||||
json.put("direction", getDirection().ordinal());
|
||||
json.put("heldItem", heldItem);
|
||||
json.put("hp", hp);
|
||||
json.put("action", lastAction.ordinal());
|
||||
if (parent != null) {
|
||||
json.put("parent", parent.getUsername()); //Only used client-side for now
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static Cubot deserialize(JSONObject json) {
|
||||
|
||||
Cubot cubot = new Cubot();
|
||||
cubot.setObjectId((int)(long)json.get("id"));
|
||||
cubot.setX((int)(long)json.get("x"));
|
||||
cubot.setY((int)(long)json.get("y"));
|
||||
cubot.hp = (int)(long)json.get("hp");
|
||||
cubot.setDirection(Direction.getDirection((int)(long)json.get("direction")));
|
||||
cubot.heldItem = (int)(long)json.get("heldItem");
|
||||
|
||||
return cubot;
|
||||
|
||||
}
|
||||
|
||||
public void setHeldItem(int heldItem) {
|
||||
this.heldItem = heldItem;
|
||||
}
|
||||
|
||||
public int getHeldItem() {
|
||||
return heldItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKeyboardBuffer(ArrayList<Integer> kbBuffer) {
|
||||
keyboardBuffer = kbBuffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Integer> getKeyboardBuffer() {
|
||||
return keyboardBuffer;
|
||||
}
|
||||
|
||||
public void clearKeyboardBuffer(){
|
||||
keyboardBuffer.clear();
|
||||
}
|
||||
|
||||
public void setCurrentAction(CubotAction currentAction) {
|
||||
this.currentAction = currentAction;
|
||||
}
|
||||
|
||||
public User getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(User parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public CubotAction getAction() {
|
||||
return lastAction;
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
public enum CubotAction {
|
||||
IDLE,
|
||||
DIGGING,
|
||||
WALKING,
|
||||
WITHDRAWING,
|
||||
DEPOSITING
|
||||
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.assembly.CpuHardware;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.TileMap;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class CubotDrill extends CpuHardware {
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
static final char HWID = 0x0005;
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 5;
|
||||
|
||||
private static final int POLL = 1;
|
||||
private static final int GATHER_SLOW = 2;
|
||||
private static final int GATHER_FAST = 3;
|
||||
|
||||
private Cubot cubot;
|
||||
|
||||
public CubotDrill(Cubot cubot) {
|
||||
this.cubot = cubot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
if (a == POLL) {
|
||||
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(0);
|
||||
|
||||
} else if (a == GATHER_SLOW || a == GATHER_FAST) {
|
||||
|
||||
if (cubot.getAction() != CubotAction.IDLE) {
|
||||
int tile = cubot.getWorld().getTileMap().getTileAt(cubot.getX(), cubot.getY());
|
||||
|
||||
if (tile == TileMap.IRON_TILE) {
|
||||
cubot.setHeldItem(TileMap.ITEM_IRON);
|
||||
cubot.setCurrentAction(CubotAction.DIGGING);
|
||||
|
||||
} else if (tile == TileMap.COPPER_TILE) {
|
||||
cubot.setHeldItem(TileMap.ITEM_COPPER);
|
||||
cubot.setCurrentAction(CubotAction.DIGGING);
|
||||
|
||||
} else {
|
||||
//System.out.println("FAILED: dig");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("hwid", (int) HWID);
|
||||
json.put("cubot", cubot.getObjectId());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static CubotDrill deserialize(JSONObject hwJSON){
|
||||
return new CubotDrill((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((int)(long)hwJSON.get("cubot")));
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.assembly.CpuHardware;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class CubotInventory extends CpuHardware {
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
static final char HWID = 0x0006;
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 6;
|
||||
|
||||
private Cubot cubot;
|
||||
|
||||
private static final int POLL = 1;
|
||||
private static final int CLEAR = 2;
|
||||
|
||||
public CubotInventory(Cubot cubot) {
|
||||
this.cubot = cubot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
if(a == POLL) {
|
||||
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(cubot.getHeldItem());
|
||||
|
||||
} else if (a == CLEAR) {
|
||||
cubot.setHeldItem(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("hwid", (int) HWID);
|
||||
json.put("cubot", cubot.getObjectId());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static CubotInventory deserialize(JSONObject hwJSON){
|
||||
return new CubotInventory((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((int)(long)hwJSON.get("cubot")));
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.assembly.CpuHardware;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.GameObject;
|
||||
import net.simon987.server.game.InventoryHolder;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CubotLaser extends CpuHardware {
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
static final char HWID = 0x0002;
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 2;
|
||||
|
||||
private Cubot cubot;
|
||||
|
||||
private static final int WITHDRAW = 1;
|
||||
|
||||
|
||||
public CubotLaser(Cubot cubot) {
|
||||
this.cubot = cubot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||
|
||||
|
||||
if(a == WITHDRAW) {
|
||||
|
||||
//System.out.println("withdraw");
|
||||
|
||||
Point frontTile = cubot.getFrontTile();
|
||||
ArrayList<GameObject> objects = cubot.getWorld().getGameObjectsAt(frontTile.x, frontTile.y);
|
||||
|
||||
|
||||
if (cubot.getAction() != CubotAction.IDLE && objects.size() > 0) {
|
||||
|
||||
if (objects.get(0) instanceof InventoryHolder) {
|
||||
//Take the item
|
||||
if (((InventoryHolder) objects.get(0)).takeItem(b)) {
|
||||
|
||||
cubot.setHeldItem(b);
|
||||
//System.out.println("took " + b);
|
||||
cubot.setCurrentAction(CubotAction.WITHDRAWING);
|
||||
|
||||
} else {
|
||||
//The inventory holder can't provide this item
|
||||
//todo Add emote here
|
||||
// System.out.println("DEBUG: FAILED: take (The inventory holder can't provide this item)");
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
//Nothing in front
|
||||
// System.out.println("DEBUG: FAILED: take (Nothing in front or Cubot is busy)");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("hwid", (int) HWID);
|
||||
json.put("cubot", cubot.getObjectId());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static CubotLaser deserialize(JSONObject hwJSON){
|
||||
return new CubotLaser((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((int)(long)hwJSON.get("cubot")));
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.assembly.CpuHardware;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.Direction;
|
||||
import net.simon987.server.io.JSONSerialisable;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class CubotLeg extends CpuHardware implements JSONSerialisable {
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 1;
|
||||
|
||||
public static final String NAME = "Cubot Leg";
|
||||
|
||||
private static final int SET_DIR = 1;
|
||||
private static final int SET_DIR_AND_WALK = 2;
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
static final char HWID = 0x0001;
|
||||
|
||||
private Cubot cubot;
|
||||
|
||||
public CubotLeg(Cubot cubot) {
|
||||
this.cubot = cubot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||
|
||||
if(a == SET_DIR){
|
||||
|
||||
Direction dir = Direction.getDirection(b);
|
||||
|
||||
if(dir != null){
|
||||
cubot.setDirection(Direction.getDirection(b));
|
||||
status.setErrorFlag(false);
|
||||
} else {
|
||||
status.setErrorFlag(true);
|
||||
}
|
||||
|
||||
|
||||
} else if(a == SET_DIR_AND_WALK){
|
||||
|
||||
Direction dir = Direction.getDirection(b);
|
||||
|
||||
if(dir != null){
|
||||
cubot.setDirection(Direction.getDirection(b));
|
||||
status.setErrorFlag(false);
|
||||
} else {
|
||||
status.setErrorFlag(true);
|
||||
}
|
||||
|
||||
cubot.setCurrentAction(CubotAction.WALKING);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("hwid", (int) HWID);
|
||||
json.put("cubot", cubot.getObjectId());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static CubotLeg deserialize(JSONObject hwJSON){
|
||||
return new CubotLeg((Cubot)GameServer.INSTANCE.getGameUniverse().getObject((int)(long)hwJSON.get("cubot")));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.assembly.CpuHardware;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.World;
|
||||
import net.simon987.server.game.pathfinding.Node;
|
||||
import net.simon987.server.game.pathfinding.Pathfinder;
|
||||
import net.simon987.server.io.JSONSerialisable;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CubotLidar extends CpuHardware implements JSONSerialisable {
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
public static final char HWID = 0x0003;
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 3;
|
||||
|
||||
private Cubot cubot;
|
||||
|
||||
private static final int GET_POS = 1;
|
||||
private static final int GET_PATH = 2;
|
||||
private static final int GET_MAP = 3;
|
||||
|
||||
private static final int MEMORY_MAP_START = 0x0100;
|
||||
private static final int MEMORY_PATH_START = 0x0000;
|
||||
|
||||
public CubotLidar(Cubot cubot) {
|
||||
this.cubot = cubot;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
switch (a){
|
||||
case GET_POS:
|
||||
getCpu().getRegisterSet().getRegister("X").setValue(cubot.getX());
|
||||
getCpu().getRegisterSet().getRegister("Y").setValue(cubot.getY());
|
||||
break;
|
||||
case GET_PATH:
|
||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||
int destX = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||
int destY = getCpu().getRegisterSet().getRegister("Y").getValue();
|
||||
|
||||
//Get path
|
||||
ArrayList<Node> nodes = Pathfinder.findPath(cubot.getWorld(), cubot.getX(), cubot.getY(),
|
||||
destX, destY, b);
|
||||
|
||||
// System.out.println(nodes.size() + " nodes");
|
||||
|
||||
//Write to memory
|
||||
byte[] mem = getCpu().getMemory().getBytes();
|
||||
|
||||
int counter = 0; //todo get memory address from config/constant
|
||||
|
||||
if (nodes != null) {
|
||||
|
||||
Node lastNode = null;
|
||||
|
||||
for (Node n : nodes) {
|
||||
//Store the path as a sequence of directions
|
||||
|
||||
if (lastNode == null) {
|
||||
lastNode = n;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n.x < lastNode.x) {
|
||||
//West
|
||||
mem[counter++] = 0;
|
||||
mem[counter++] = 3;
|
||||
} else if (n.x > lastNode.x) {
|
||||
//East
|
||||
mem[counter++] = 0;
|
||||
mem[counter++] = 1;
|
||||
} else if (n.y < lastNode.y) {
|
||||
//North
|
||||
mem[counter++] = 0;
|
||||
mem[counter++] = 0;
|
||||
} else if (n.y > lastNode.y) {
|
||||
//South
|
||||
mem[counter++] = 0;
|
||||
mem[counter++] = 2;
|
||||
}
|
||||
|
||||
lastNode = n;
|
||||
}
|
||||
|
||||
//Indicate end of path with 0xAAAA
|
||||
mem[counter++] = -86;
|
||||
mem[counter] = -86;
|
||||
} else {
|
||||
//Indicate invalid path 0xFFFF
|
||||
mem[counter++] = -1;
|
||||
mem[counter] = -1;
|
||||
}
|
||||
|
||||
LogManager.LOGGER.fine("DEBUG: path to" + destX + "," + destY);
|
||||
break;
|
||||
|
||||
case GET_MAP:
|
||||
char[][] mapInfo = cubot.getWorld().getMapInfo();
|
||||
|
||||
int i = MEMORY_MAP_START;
|
||||
for (int y = 0; y < World.WORLD_SIZE; y++) {
|
||||
for (int x = 0; x < World.WORLD_SIZE; x++) {
|
||||
getCpu().getMemory().set(i++, mapInfo[x][y]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("hwid", (int) HWID);
|
||||
json.put("cubot", cubot.getObjectId());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static CubotLidar deserialize(JSONObject hwJSON) {
|
||||
return new CubotLidar((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((int) (long) hwJSON.get("cubot")));
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.cubotplugin.event.CpuInitialisationListener;
|
||||
import net.simon987.cubotplugin.event.UserCreationListener;
|
||||
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.plugin.ServerPlugin;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class CubotPlugin extends ServerPlugin implements GameObjectDeserializer, CpuHardwareDeserializer{
|
||||
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
listeners.add(new CpuInitialisationListener());
|
||||
listeners.add(new UserCreationListener());
|
||||
|
||||
LogManager.LOGGER.info("Initialised Cubot plugin");
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameObject deserializeObject(JSONObject object) {
|
||||
|
||||
int objType = (int)(long)object.get("type");
|
||||
|
||||
if(objType == Cubot.ID) {
|
||||
|
||||
return Cubot.deserialize(object);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CpuHardware deserializeHardware(JSONObject hwJson) {
|
||||
int hwid = (int)(long)hwJson.get("hwid");
|
||||
|
||||
switch (hwid){
|
||||
case CubotLeg.HWID:
|
||||
return CubotLeg.deserialize(hwJson);
|
||||
case CubotLaser.HWID:
|
||||
return CubotLaser.deserialize(hwJson);
|
||||
case CubotLidar.HWID:
|
||||
return CubotLidar.deserialize(hwJson);
|
||||
case CubotDrill.HWID:
|
||||
return CubotDrill.deserialize(hwJson);
|
||||
case CubotInventory.HWID:
|
||||
return CubotInventory.deserialize(hwJson);
|
||||
case Keyboard.HWID:
|
||||
return Keyboard.deserialize(hwJson);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
package net.simon987.cubotplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.assembly.CpuHardware;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class Keyboard extends CpuHardware {
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 4;
|
||||
|
||||
public static final String NAME = "Wireless Keyboard";
|
||||
|
||||
|
||||
private static final int CLEAR_BUFFER = 0;
|
||||
private static final int FETCH_KEY = 1;
|
||||
|
||||
/**
|
||||
* Hardware ID (Should be unique)
|
||||
*/
|
||||
public static final char HWID = 0x0004;
|
||||
|
||||
private Cubot cubot;
|
||||
|
||||
public Keyboard(Cubot cubot) {
|
||||
this.cubot = cubot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
if(a == CLEAR_BUFFER){
|
||||
|
||||
cubot.clearKeyboardBuffer();
|
||||
|
||||
} else if (a == FETCH_KEY){
|
||||
//pop
|
||||
int key = 0;
|
||||
if(cubot.getKeyboardBuffer().size() > 0){
|
||||
key = cubot.getKeyboardBuffer().get(0);
|
||||
cubot.getKeyboardBuffer().remove(0);
|
||||
}
|
||||
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(key);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("hwid", (int) HWID);
|
||||
json.put("cubot", cubot.getObjectId());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static Keyboard deserialize(JSONObject hwJSON){
|
||||
return new Keyboard((Cubot) GameServer.INSTANCE.getGameUniverse().getObject((int)(long)hwJSON.get("cubot")));
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package net.simon987.cubotplugin.event;
|
||||
|
||||
import net.simon987.cubotplugin.*;
|
||||
import net.simon987.server.assembly.CPU;
|
||||
import net.simon987.server.event.CpuInitialisationEvent;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.event.GameEventListener;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.user.User;
|
||||
|
||||
public class CpuInitialisationListener implements GameEventListener {
|
||||
@Override
|
||||
public Class getListenedEventType() {
|
||||
return CpuInitialisationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(GameEvent event) {
|
||||
LogManager.LOGGER.fine("(Plugin) Handled CPU Initialisation event (Cubot Plugin)");
|
||||
|
||||
CPU cpu = (CPU)event.getSource();
|
||||
User user = ((CpuInitialisationEvent)event).getUser();
|
||||
|
||||
CubotLeg legHw = new CubotLeg((Cubot) user.getControlledUnit());
|
||||
legHw.setCpu(cpu);
|
||||
CubotLaser laserHw = new CubotLaser((Cubot) user.getControlledUnit());
|
||||
laserHw.setCpu(cpu);
|
||||
CubotLidar radarHw = new CubotLidar((Cubot) user.getControlledUnit());
|
||||
radarHw.setCpu(cpu);
|
||||
Keyboard keyboard = new Keyboard((Cubot) user.getControlledUnit());
|
||||
keyboard.setCpu(cpu);
|
||||
CubotDrill drillHw = new CubotDrill((Cubot) user.getControlledUnit());
|
||||
drillHw.setCpu(cpu);
|
||||
CubotInventory invHw = new CubotInventory((Cubot) user.getControlledUnit());
|
||||
invHw.setCpu(cpu);
|
||||
|
||||
cpu.attachHardware(legHw, CubotLeg.DEFAULT_ADDRESS);
|
||||
cpu.attachHardware(laserHw, CubotLaser.DEFAULT_ADDRESS);
|
||||
cpu.attachHardware(radarHw, CubotLidar.DEFAULT_ADDRESS);
|
||||
cpu.attachHardware(keyboard, Keyboard.DEFAULT_ADDRESS);
|
||||
cpu.attachHardware(drillHw, CubotDrill.DEFAULT_ADDRESS);
|
||||
cpu.attachHardware(invHw, CubotInventory.DEFAULT_ADDRESS);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package net.simon987.cubotplugin.event;
|
||||
|
||||
import net.simon987.cubotplugin.Cubot;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.event.GameEventListener;
|
||||
import net.simon987.server.event.UserCreationEvent;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.user.User;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class UserCreationListener implements GameEventListener {
|
||||
@Override
|
||||
public Class getListenedEventType() {
|
||||
return UserCreationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(GameEvent event) {
|
||||
|
||||
User user = (User)event.getSource();
|
||||
|
||||
LogManager.LOGGER.fine("(Plugin) Handled User creation event (Cubot Plugin)");
|
||||
|
||||
Cubot cubot = new Cubot();
|
||||
|
||||
cubot.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(
|
||||
GameServer.INSTANCE.getConfig().getInt("new_user_worldX"),
|
||||
GameServer.INSTANCE.getConfig().getInt("new_user_worldY")));
|
||||
cubot.getWorld().getGameObjects().add(cubot);
|
||||
|
||||
cubot.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
||||
|
||||
cubot.setHeldItem(GameServer.INSTANCE.getConfig().getInt("new_user_item"));
|
||||
|
||||
cubot.setParent(user);
|
||||
|
||||
Point point = cubot.getWorld().getRandomPassableTile();
|
||||
|
||||
cubot.setX(point.x);
|
||||
cubot.setY(point.y);
|
||||
|
||||
user.setControlledUnit(cubot);
|
||||
|
||||
}
|
||||
}
|
@ -3,17 +3,10 @@ package net.simon987.cubotplugin;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class CubotTest {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
assertEquals(1,2);
|
||||
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
classpath=net.simon987.kilnplugin.KilnPlugin
|
||||
name=Kiln Plugin
|
||||
version=1.0
|
@ -1,21 +0,0 @@
|
||||
package net.simon987.kilnplugin;
|
||||
|
||||
import net.simon987.server.game.GameObject;
|
||||
import net.simon987.server.io.GameObjectDeserializer;
|
||||
import net.simon987.server.plugin.ServerPlugin;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class KilnPlugin extends ServerPlugin implements GameObjectDeserializer {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameObject deserializeObject(JSONObject object) {
|
||||
return null;
|
||||
}
|
||||
}
|
58
Plugin Misc HW/Plugin Misc HW.iml
Normal file
58
Plugin Misc HW/Plugin Misc HW.iml
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
<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="module" module-name="Server" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-sync:3.9.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mongodb:bson:3.9.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: junit:junit:4.10" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
||||
</component>
|
||||
</module>
|
32
Plugin Misc HW/pom.xml
Normal file
32
Plugin Misc HW/pom.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?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.pluginmischw</groupId>
|
||||
<artifactId>plugin-misc-hw</artifactId>
|
||||
<version>1.4a</version>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.simon987.server</groupId>
|
||||
<artifactId>server</artifactId>
|
||||
<version>1.4a</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
<artifactId>json-simple</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,52 @@
|
||||
package net.simon987.mischwplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.assembly.HardwareModule;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.assembly.Util;
|
||||
import net.simon987.server.game.objects.ControllableUnit;
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* Hardware to get game time
|
||||
*/
|
||||
public class Clock extends HardwareModule {
|
||||
|
||||
private static final char HWID = 0x0008;
|
||||
|
||||
public static final char DEFAULT_ADDRESS = 0x0008;
|
||||
|
||||
public Clock() {
|
||||
|
||||
}
|
||||
|
||||
public Clock(Document document, ControllableUnit unit) {
|
||||
super(document, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
int time = (int) GameServer.INSTANCE.getGameUniverse().getTime();
|
||||
|
||||
//Will need to be changed to quadword in about 136 years
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(Util.getHigherWord(time));
|
||||
getCpu().getRegisterSet().getRegister("C").setValue(Util.getLowerWord(time));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
|
||||
Document dbObject = new Document();
|
||||
dbObject.put("type", getClass().getCanonicalName());
|
||||
|
||||
return dbObject;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package net.simon987.mischwplugin;
|
||||
|
||||
import net.simon987.mischwplugin.event.CpuInitialisationListener;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.game.objects.GameRegistry;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.plugin.ServerPlugin;
|
||||
|
||||
/**
|
||||
* Plugin that adds miscellaneous hardware to the game
|
||||
*/
|
||||
public class MiscHWPlugin extends ServerPlugin {
|
||||
|
||||
|
||||
@Override
|
||||
public void init(GameServer gameServer) {
|
||||
listeners.add(new CpuInitialisationListener());
|
||||
|
||||
GameRegistry registry = gameServer.getRegistry();
|
||||
|
||||
registry.registerHardware(RandomNumberGenerator.class);
|
||||
registry.registerHardware(Clock.class);
|
||||
|
||||
LogManager.LOGGER.info("(Mist HW Plugin) Initialised Misc Hardware Plugin");
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package net.simon987.mischwplugin;
|
||||
|
||||
import net.simon987.server.assembly.HardwareModule;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.game.objects.ControllableUnit;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Hardware to generate random numbers
|
||||
*/
|
||||
public class RandomNumberGenerator extends HardwareModule {
|
||||
|
||||
private static final char HWID = 0x0007;
|
||||
|
||||
public static final char DEFAULT_ADDRESS = 0x0007;
|
||||
|
||||
private Random random;
|
||||
|
||||
public RandomNumberGenerator() {
|
||||
random = new Random();
|
||||
}
|
||||
|
||||
public RandomNumberGenerator(Document document, ControllableUnit unit) {
|
||||
super(document, unit);
|
||||
random = new Random();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(random.nextInt(0xFFFF));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
|
||||
Document dbObject = new Document();
|
||||
dbObject.put("type", getClass().getCanonicalName());
|
||||
|
||||
return dbObject;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package net.simon987.mischwplugin.event;
|
||||
|
||||
import net.simon987.mischwplugin.Clock;
|
||||
import net.simon987.mischwplugin.RandomNumberGenerator;
|
||||
import net.simon987.server.assembly.CPU;
|
||||
import net.simon987.server.event.CpuInitialisationEvent;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.event.GameEventListener;
|
||||
import net.simon987.server.game.objects.HardwareHost;
|
||||
|
||||
public class CpuInitialisationListener implements GameEventListener {
|
||||
|
||||
@Override
|
||||
public Class getListenedEventType() {
|
||||
return CpuInitialisationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(GameEvent event) {
|
||||
|
||||
CPU cpu = (CPU) event.getSource();
|
||||
HardwareHost cubot = (HardwareHost) ((CpuInitialisationEvent) event).getUnit();
|
||||
cpu.setHardwareHost(cubot);
|
||||
|
||||
RandomNumberGenerator rngHW = new RandomNumberGenerator();
|
||||
rngHW.setCpu(cpu);
|
||||
Clock clock = new Clock();
|
||||
clock.setCpu(cpu);
|
||||
|
||||
cpu.getHardwareHost().attachHardware(rngHW, RandomNumberGenerator.DEFAULT_ADDRESS);
|
||||
cpu.getHardwareHost().attachHardware(clock, Clock.DEFAULT_ADDRESS);
|
||||
}
|
||||
}
|
3
Plugin Misc HW/src/main/resources/plugin.properties
Normal file
3
Plugin Misc HW/src/main/resources/plugin.properties
Normal file
@ -0,0 +1,3 @@
|
||||
classpath=net.simon987.mischwplugin.MiscHWPlugin
|
||||
name=Misc HW Plugin
|
||||
version=1.0
|
58
Plugin NPC/Plugin NPC.iml
Normal file
58
Plugin NPC/Plugin NPC.iml
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
<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: 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: org.hamcrest:hamcrest-core:1.1" level="project" />
|
||||
<orderEntry type="module" module-name="Server" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-sync:3.9.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mongodb:bson:3.9.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>
|
||||
</module>
|
31
Plugin NPC/pom.xml
Normal file
31
Plugin NPC/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.pluginnpc</groupId>
|
||||
<artifactId>plugin-npc</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>
|
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
157
Plugin NPC/src/main/java/net/simon987/npcplugin/Factory.java
Normal file
157
Plugin NPC/src/main/java/net/simon987/npcplugin/Factory.java
Normal file
@ -0,0 +1,157 @@
|
||||
package net.simon987.npcplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.game.objects.MessageReceiver;
|
||||
import net.simon987.server.game.objects.Structure;
|
||||
import net.simon987.server.game.objects.Updatable;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Game objects that regularly creates NonPlayerCharacters
|
||||
*/
|
||||
public class Factory extends Structure implements Updatable, MessageReceiver {
|
||||
|
||||
private static final int MAP_INFO = 0x0401;
|
||||
|
||||
/**
|
||||
* Maximum number of NonPlayerCharacters assigned to this Factory
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* Number of ticks to wait until the Factory can spawn a new NPC
|
||||
*/
|
||||
private int cooldown = 0;
|
||||
|
||||
private boolean locked = true;
|
||||
|
||||
/**
|
||||
* If non-null, the next spawned NPC will be a HackedNPC and the program will be
|
||||
* injected in its memory
|
||||
*/
|
||||
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
|
||||
public char getMapInfo() {
|
||||
return MAP_INFO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick
|
||||
* <br>The fist time this is called, NPCs retrieved from the database are linked to the Factory
|
||||
*/
|
||||
@Override
|
||||
public void update() {
|
||||
|
||||
Settlement settlement = NpcPlugin.settlementMap.get(getWorld().getId());
|
||||
|
||||
if (settlement == null) {
|
||||
//Only happens when server is killed during save function
|
||||
getWorld().decUpdatable();
|
||||
setDead(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cooldown == 0) {
|
||||
if (settlement.getNpcs().size() < MAX_NPC_COUNT) {
|
||||
Point p = getAdjacentTile();
|
||||
|
||||
if (p != null) {
|
||||
NonPlayerCharacter npc = spawnNPC(p);
|
||||
settlement.addNpc(npc);
|
||||
|
||||
getWorld().addObject(npc);
|
||||
getWorld().incUpdatable();
|
||||
}
|
||||
}
|
||||
|
||||
cooldown += NPC_CREATION_COOLDOWN;
|
||||
|
||||
} else {
|
||||
cooldown--;
|
||||
}
|
||||
}
|
||||
|
||||
private NonPlayerCharacter spawnNPC(Point p) {
|
||||
|
||||
NonPlayerCharacter npc;
|
||||
|
||||
if (programIndex == 0) {
|
||||
npc = spawnRandomNpc(p);
|
||||
} else {
|
||||
npc = spawnHackedNpc(p);
|
||||
}
|
||||
|
||||
return npc;
|
||||
}
|
||||
|
||||
private NonPlayerCharacter spawnRandomNpc(Point p) {
|
||||
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) {
|
||||
|
||||
if (programIndex == 0) {
|
||||
program = new char[PROGRAM_SIZE];
|
||||
}
|
||||
|
||||
System.arraycopy(message, 0, program, programIndex, message.length);
|
||||
programIndex += message.length;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
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();
|
||||
}
|
||||
}
|
107
Plugin NPC/src/main/java/net/simon987/npcplugin/HarvestTask.java
Normal file
107
Plugin NPC/src/main/java/net/simon987/npcplugin/HarvestTask.java
Normal file
@ -0,0 +1,107 @@
|
||||
package net.simon987.npcplugin;
|
||||
|
||||
|
||||
import net.simon987.server.assembly.Util;
|
||||
import net.simon987.server.game.objects.Direction;
|
||||
import net.simon987.server.game.objects.GameObject;
|
||||
import net.simon987.server.game.objects.InventoryHolder;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Find Biomass, move towards it, collect it, repeat
|
||||
*/
|
||||
public class HarvestTask extends NPCTask {
|
||||
|
||||
private Random random;
|
||||
|
||||
/**
|
||||
* Number of ticks to wait before continuing
|
||||
*/
|
||||
private int pause;
|
||||
|
||||
/**
|
||||
* Direction of the next world to visit (randomly chosen)
|
||||
*/
|
||||
private Direction nextWorldDirection = null;
|
||||
|
||||
public HarvestTask() {
|
||||
random = new Random();
|
||||
pause = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This task never finishes
|
||||
*/
|
||||
@Override
|
||||
public boolean checkCompleted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(NonPlayerCharacter npc) {
|
||||
|
||||
if (pause == 0) {
|
||||
//Get biomass
|
||||
ArrayList<GameObject> biomass = npc.getWorld().findGameObjects("net.simon987.biomassplugin.BiomassBlob");
|
||||
|
||||
//Get closest one
|
||||
int minDist = Integer.MAX_VALUE;
|
||||
GameObject minBiomass = null;
|
||||
|
||||
for (GameObject plant : biomass) {
|
||||
|
||||
int dist = Util.manhattanDist(npc.getX(), npc.getY(), plant.getX(), plant.getY());
|
||||
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
minBiomass = plant;
|
||||
}
|
||||
}
|
||||
|
||||
//Move towards it
|
||||
if (minBiomass != null && minDist == 1) {
|
||||
//Reached biomass, change direction to face it
|
||||
Direction newDirection = Direction.getFacing(npc.getX(), npc.getY(),
|
||||
minBiomass.getX(), minBiomass.getY());
|
||||
|
||||
if (newDirection != null) {
|
||||
npc.setDirection(newDirection);
|
||||
|
||||
//Reached biomass, harvest it
|
||||
if (minBiomass instanceof InventoryHolder) {
|
||||
((InventoryHolder) minBiomass).takeItem(1);
|
||||
pause += 6;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
LogManager.LOGGER.severe("FIXME: tick:HarvestTask, Direction is null");
|
||||
}
|
||||
|
||||
nextWorldDirection = null;
|
||||
} else if (minBiomass != null && npc.moveTo(minBiomass.getX(), minBiomass.getY(), 1)) {
|
||||
//Moving towards biomass...
|
||||
nextWorldDirection = null;
|
||||
} else {
|
||||
|
||||
if (nextWorldDirection == null) {
|
||||
|
||||
while (!npc.gotoWorld(nextWorldDirection)) {
|
||||
nextWorldDirection = Direction.getDirection(random.nextInt(4));
|
||||
}
|
||||
|
||||
pause += 6;
|
||||
} else {
|
||||
npc.gotoWorld(nextWorldDirection);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
pause--;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package net.simon987.npcplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.event.ObjectDeathEvent;
|
||||
import net.simon987.server.game.objects.Direction;
|
||||
import org.bson.Document;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
|
||||
public class HarvesterNPC extends NonPlayerCharacter {
|
||||
|
||||
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 HarvesterNPC() {
|
||||
setTask(new HarvestTask());
|
||||
|
||||
setHp(MAX_HEALTH);
|
||||
setMaxHp(MAX_HEALTH);
|
||||
setHealRate(HEAL_RATE);
|
||||
}
|
||||
|
||||
public HarvesterNPC(Document document) {
|
||||
super(document);
|
||||
|
||||
setTask(new HarvestTask());
|
||||
|
||||
setDirection(Direction.getDirection(document.getInteger("direction")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
|
||||
if (getSettlement() != null) {
|
||||
if (getTask().checkCompleted()) {
|
||||
|
||||
setTask(new HarvestTask());
|
||||
|
||||
} else {
|
||||
getTask().tick(this);
|
||||
}
|
||||
|
||||
//Self-destroy when age limit is reached
|
||||
if (getAge() >= NonPlayerCharacter.LIFETIME) {
|
||||
setDead(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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 jsonSerialise() {
|
||||
JSONObject json = super.jsonSerialise();
|
||||
|
||||
json.put("direction", getDirection().ordinal());
|
||||
json.put("hp", getHp());
|
||||
json.put("action", getAction().ordinal());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject debugJsonSerialise() {
|
||||
JSONObject json = jsonSerialise();
|
||||
|
||||
json.put("taskCompleted", getTask().checkCompleted());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
Document dbObject = super.mongoSerialise();
|
||||
|
||||
dbObject.put("direction", getDirection().ordinal());
|
||||
dbObject.put("hp", getHp());
|
||||
dbObject.put("action", getAction().ordinal());
|
||||
|
||||
return dbObject;
|
||||
}
|
||||
}
|
10
Plugin NPC/src/main/java/net/simon987/npcplugin/NPCTask.java
Normal file
10
Plugin NPC/src/main/java/net/simon987/npcplugin/NPCTask.java
Normal file
@ -0,0 +1,10 @@
|
||||
package net.simon987.npcplugin;
|
||||
|
||||
|
||||
public abstract class NPCTask {
|
||||
|
||||
public abstract boolean checkCompleted();
|
||||
|
||||
public abstract void tick(NonPlayerCharacter npc);
|
||||
|
||||
}
|
@ -0,0 +1,255 @@
|
||||
package net.simon987.npcplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.assembly.Util;
|
||||
import net.simon987.server.game.objects.*;
|
||||
import net.simon987.server.game.pathfinding.Node;
|
||||
import net.simon987.server.game.pathfinding.Pathfinder;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import org.bson.Document;
|
||||
|
||||
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 {
|
||||
|
||||
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");
|
||||
|
||||
/**
|
||||
* Number of ticks to live
|
||||
*/
|
||||
public static final int LIFETIME = GameServer.INSTANCE.getConfig().getInt("npc_lifetime");
|
||||
|
||||
// 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_REGEN_RATE_DEFAULT = 0;
|
||||
|
||||
/**
|
||||
* Current task
|
||||
*/
|
||||
private NPCTask task;
|
||||
|
||||
/**
|
||||
* Action at the end of the last tick
|
||||
*/
|
||||
private Action lastAction = Action.IDLE;
|
||||
|
||||
private Settlement settlement;
|
||||
|
||||
/**
|
||||
* Age of the npc, in ticks
|
||||
*/
|
||||
private int age = 0;
|
||||
|
||||
/**
|
||||
* Current health of the npc
|
||||
*/
|
||||
private int hp = HP_MAX_DEFAULT;
|
||||
|
||||
/**
|
||||
* Health regeneration rate of the npc
|
||||
*/
|
||||
private int hpRegenerationRate = HP_REGEN_RATE_DEFAULT;
|
||||
|
||||
/**
|
||||
* Maximum health of the npc
|
||||
*/
|
||||
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
|
||||
public char getMapInfo() {
|
||||
return MAP_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
|
||||
age++;
|
||||
|
||||
//Destroy NPCs that are not linked with a Settlement
|
||||
if (settlement == null) {
|
||||
setDead(true);
|
||||
}
|
||||
|
||||
//Heal the NPC
|
||||
heal(hpRegenerationRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to move the NPC to the specified coordinates
|
||||
*
|
||||
* @param range distance to the desired coordinates, in tiles
|
||||
* @return true if the path is passable
|
||||
*/
|
||||
boolean moveTo(int x, int y, int range) {
|
||||
|
||||
ArrayList<Node> path = Pathfinder.findPath(getWorld(), getX(), getY(), x, y, range);
|
||||
|
||||
if (path != null && path.size() > 0) {
|
||||
|
||||
Node nextTile = path.get(1);
|
||||
|
||||
Direction newDirection = Direction.getFacing(getX(), getY(), nextTile.x, nextTile.y);
|
||||
|
||||
if (newDirection != null) {
|
||||
setDirection(newDirection);
|
||||
} else {
|
||||
LogManager.LOGGER.severe("FIXME: moveTo:NonPlayerCharacter, Direction is null");
|
||||
}
|
||||
|
||||
if (incrementLocation()) {
|
||||
lastAction = Action.WALKING;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
lastAction = Action.IDLE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to the next World in the specified Direction.
|
||||
*
|
||||
* @return true if the World in the specified Direction is within the max. distance from the Factory
|
||||
*/
|
||||
boolean gotoWorld(Direction direction) {
|
||||
|
||||
if (direction == Direction.NORTH) {
|
||||
|
||||
if (Util.manhattanDist(settlement.getWorld().getX(), settlement.getWorld().getY(),
|
||||
getWorld().getX(), getWorld().getY() - 1) <= MAX_FACTORY_DISTANCE) {
|
||||
if (!moveTo(8, 0, 0)) {
|
||||
setDirection(Direction.NORTH);
|
||||
incrementLocation();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (direction == Direction.EAST) {
|
||||
if (Util.manhattanDist(settlement.getWorld().getX(), settlement.getWorld().getY(),
|
||||
getWorld().getX() + 1, getWorld().getY()) <= MAX_FACTORY_DISTANCE) {
|
||||
if (!moveTo(15, 7, 0)) {
|
||||
setDirection(Direction.EAST);
|
||||
incrementLocation();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (direction == Direction.SOUTH) {
|
||||
if (Util.manhattanDist(settlement.getWorld().getX(), settlement.getWorld().getY(),
|
||||
getWorld().getX(), getWorld().getY() + 1) <= MAX_FACTORY_DISTANCE) {
|
||||
if (!moveTo(8, 15, 0)) {
|
||||
setDirection(Direction.SOUTH);
|
||||
incrementLocation();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (direction == Direction.WEST) {
|
||||
if (Util.manhattanDist(settlement.getWorld().getX(), settlement.getWorld().getY(),
|
||||
getWorld().getX() - 1, getWorld().getY()) <= MAX_FACTORY_DISTANCE) {
|
||||
if (!moveTo(0, 7, 0)) {
|
||||
setDirection(Direction.WEST);
|
||||
incrementLocation();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHealRate(int hp) {
|
||||
hpRegenerationRate = hp;
|
||||
}
|
||||
|
||||
@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 heal(int amount) {
|
||||
hp += amount;
|
||||
|
||||
//Can't heal above max
|
||||
if (hp > maxHp) {
|
||||
hp = maxHp;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage(int amount) {
|
||||
hp -= amount;
|
||||
|
||||
//YOU ARE DEAD
|
||||
if (hp <= 0) {
|
||||
setDead(true);
|
||||
}
|
||||
}
|
||||
|
||||
public NPCTask getTask() {
|
||||
return task;
|
||||
}
|
||||
|
||||
public void setTask(NPCTask task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public Action getAction() {
|
||||
return lastAction;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
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);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package net.simon987.npcplugin;
|
||||
|
||||
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.world.TileVaultFloor;
|
||||
import net.simon987.npcplugin.world.TileVaultWall;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.IServerConfiguration;
|
||||
import net.simon987.server.game.objects.GameRegistry;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.plugin.ServerPlugin;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class NpcPlugin extends ServerPlugin {
|
||||
|
||||
public static Map<String, Settlement> settlementMap;
|
||||
|
||||
public static Document DEFAULT_HACKED_NPC;
|
||||
|
||||
@Override
|
||||
public void init(GameServer gameServer) {
|
||||
|
||||
IServerConfiguration configuration = gameServer.getConfig();
|
||||
GameRegistry registry = gameServer.getRegistry();
|
||||
|
||||
listeners.add(new WorldCreationListener(configuration.getInt("settlement_spawn_rate")));
|
||||
listeners.add(new CpuInitialisationListener());
|
||||
listeners.add(new VaultWorldUpdateListener(configuration));
|
||||
listeners.add(new VaultCompleteListener());
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
public Document mongoSerialise() {
|
||||
Document document = super.mongoSerialise();
|
||||
|
||||
Document settlements = new Document();
|
||||
for (String world : settlementMap.keySet()) {
|
||||
settlements.put(world, settlementMap.get(world).mongoSerialise());
|
||||
}
|
||||
|
||||
document.put("settlement_map", settlements);
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Document document) {
|
||||
super.load(document);
|
||||
|
||||
Document settlements = (Document) document.get("settlement_map");
|
||||
|
||||
for (String world : settlements.keySet()) {
|
||||
settlementMap.put(world, new Settlement((Document) settlements.get(world)));
|
||||
}
|
||||
|
||||
LogManager.LOGGER.fine(String.format("(%s) Loaded %d settlements", name, settlementMap.size()));
|
||||
}
|
||||
}
|
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;
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package net.simon987.npcplugin;
|
||||
|
||||
import net.simon987.server.assembly.HardwareModule;
|
||||
import net.simon987.server.assembly.Status;
|
||||
import net.simon987.server.assembly.Util;
|
||||
import net.simon987.server.game.objects.Action;
|
||||
import net.simon987.server.game.objects.ControllableUnit;
|
||||
import org.bson.Document;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RadioReceiverHardware extends HardwareModule {
|
||||
|
||||
public static final char HWID = 0xC; //12
|
||||
|
||||
private static final int LISTEN = 1;
|
||||
|
||||
public static final int DEFAULT_ADDRESS = 0xC;
|
||||
|
||||
private ControllableUnit cubot;
|
||||
|
||||
public RadioReceiverHardware(ControllableUnit cubot) {
|
||||
this.cubot = cubot;
|
||||
}
|
||||
|
||||
public RadioReceiverHardware(Document document, ControllableUnit unit) {
|
||||
super(document, unit);
|
||||
|
||||
this.cubot = unit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInterrupt(Status status) {
|
||||
int x = getCpu().getRegisterSet().getRegister("X").getValue();
|
||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||
|
||||
if (a == LISTEN) {
|
||||
|
||||
//Find the nearest Radio Tower and query it
|
||||
cubot.setAction(Action.LISTENING);
|
||||
|
||||
List<char[]> messages = new ArrayList<>(6);
|
||||
|
||||
for (String world : NpcPlugin.settlementMap.keySet()) {
|
||||
RadioTower tower = NpcPlugin.settlementMap.get(world).getRadioTower();
|
||||
|
||||
if (tower != null && Util.manhattanDist(
|
||||
tower.getWorld().getX(), tower.getWorld().getY(),
|
||||
cubot.getWorld().getX(), cubot.getWorld().getY()) <= RadioTower.MAX_RANGE) {
|
||||
//Tower is in range
|
||||
messages.addAll(tower.getMessages());
|
||||
}
|
||||
}
|
||||
|
||||
//Write messages to memory
|
||||
int offset = 0;
|
||||
|
||||
for (char[] message : messages) {
|
||||
|
||||
getCpu().getMemory().write(x + offset, message, 0, message.length);
|
||||
offset += message.length;
|
||||
}
|
||||
|
||||
//Write the amount of messages received to B
|
||||
getCpu().getRegisterSet().getRegister("B").setValue(messages.size());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getId() {
|
||||
return HWID;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
|
||||
Document dbObject = new Document();
|
||||
|
||||
dbObject.put("type", getClass().getCanonicalName());
|
||||
dbObject.put("cubot", cubot.getObjectId());
|
||||
|
||||
return dbObject;
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package net.simon987.npcplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.game.objects.MessageReceiver;
|
||||
import net.simon987.server.game.objects.Structure;
|
||||
import net.simon987.server.game.objects.Updatable;
|
||||
import org.bson.Document;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class RadioTower extends Structure implements MessageReceiver, Updatable {
|
||||
|
||||
private static final int MAP_INFO = 0x0901;
|
||||
|
||||
public static final int MAX_RANGE = GameServer.INSTANCE.getConfig().getInt("radio_tower_range");
|
||||
|
||||
private static final int MAX_MESSAGES = 16;
|
||||
|
||||
public RadioTower() {
|
||||
super(1, 1);
|
||||
}
|
||||
|
||||
public RadioTower(Document document) {
|
||||
super(document, 1, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getMapInfo() {
|
||||
return MAP_INFO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Messages from the current tick
|
||||
*/
|
||||
private ArrayList<char[]> messages = new ArrayList<>(4);
|
||||
|
||||
/**
|
||||
* Messages from the last tick
|
||||
*/
|
||||
private ArrayList<char[]> lastMessages = new ArrayList<>(4);
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
lastMessages = new ArrayList<>(messages);
|
||||
messages.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendMessage(char[] message) {
|
||||
|
||||
if (message.length < MAX_MESSAGES) {
|
||||
messages.add(message);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<char[]> getMessages() {
|
||||
return lastMessages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject debugJsonSerialise() {
|
||||
JSONObject json = super.debugJsonSerialise();
|
||||
|
||||
JSONArray messages = new JSONArray();
|
||||
|
||||
for (char[] message : this.messages) {
|
||||
messages.add(new String(message));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package net.simon987.npcplugin.event;
|
||||
|
||||
import net.simon987.npcplugin.RadioReceiverHardware;
|
||||
import net.simon987.server.assembly.CPU;
|
||||
import net.simon987.server.event.CpuInitialisationEvent;
|
||||
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.HardwareHost;
|
||||
|
||||
public class CpuInitialisationListener implements GameEventListener {
|
||||
@Override
|
||||
public Class getListenedEventType() {
|
||||
return CpuInitialisationEvent.class;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(GameEvent event) {
|
||||
CPU cpu = (CPU) event.getSource();
|
||||
ControllableUnit controllableUnit = ((CpuInitialisationEvent) event).getUnit();
|
||||
cpu.setHardwareHost((HardwareHost) controllableUnit);
|
||||
|
||||
RadioReceiverHardware radioHw = new RadioReceiverHardware(controllableUnit);
|
||||
radioHw.setCpu(cpu);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package net.simon987.npcplugin.event;
|
||||
|
||||
import net.simon987.npcplugin.NpcPlugin;
|
||||
import net.simon987.npcplugin.Settlement;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.event.GameEventListener;
|
||||
import net.simon987.server.event.WorldGenerationEvent;
|
||||
import net.simon987.server.game.world.World;
|
||||
import net.simon987.server.game.world.WorldGenerationException;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class WorldCreationListener implements GameEventListener {
|
||||
|
||||
/**
|
||||
* Spawn rate. Higher = rarer: A factory will be spawn about every FACTORY_SPAWN_RATE generated Worlds
|
||||
*/
|
||||
private static int FACTORY_SPAWN_RATE = 0;
|
||||
|
||||
private Random random = new Random();
|
||||
|
||||
public WorldCreationListener(int factorySpawnRate) {
|
||||
FACTORY_SPAWN_RATE = factorySpawnRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getListenedEventType() {
|
||||
return WorldGenerationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(GameEvent event) {
|
||||
|
||||
if (random.nextInt(FACTORY_SPAWN_RATE) == 0) {
|
||||
|
||||
World world = (World) event.getSource();
|
||||
|
||||
try {
|
||||
Settlement settlement = new Settlement(world);
|
||||
NpcPlugin.settlementMap.put(world.getId(), settlement);
|
||||
} catch (WorldGenerationException e) {
|
||||
LogManager.LOGGER.fine(String.format("Exception during settlement generation: %s.",
|
||||
e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
4
Plugin NPC/src/main/resources/plugin.properties
Normal file
4
Plugin NPC/src/main/resources/plugin.properties
Normal file
@ -0,0 +1,4 @@
|
||||
classpath=net.simon987.npcplugin.NpcPlugin
|
||||
name=NPC Plugin
|
||||
version=1.1
|
||||
depend=Cubot Plugin
|
58
Plugin Plant/Plugin Plant.iml
Normal file
58
Plugin Plant/Plugin Plant.iml
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
<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: 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: org.hamcrest:hamcrest-core:1.1" level="project" />
|
||||
<orderEntry type="module" module-name="Server" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-sync:3.9.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mongodb:bson:3.9.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>
|
||||
</module>
|
@ -1,3 +0,0 @@
|
||||
classpath=net.simon987.plantplugin.PlantPlugin
|
||||
name=Plant Plugin
|
||||
version=1.0
|
30
Plugin Plant/pom.xml
Normal file
30
Plugin Plant/pom.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?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.pluginplant</groupId>
|
||||
<artifactId>plugin-biomassBlob</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,94 @@
|
||||
package net.simon987.biomassplugin;
|
||||
|
||||
import net.simon987.server.game.item.Item;
|
||||
import net.simon987.server.game.objects.GameObject;
|
||||
import net.simon987.server.game.objects.InventoryHolder;
|
||||
import org.bson.Document;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class BiomassBlob extends GameObject implements InventoryHolder {
|
||||
|
||||
private static final char MAP_INFO = 0x0101;
|
||||
|
||||
/**
|
||||
* Yield of the blob, in biomass units
|
||||
*/
|
||||
private int biomassCount;
|
||||
|
||||
public BiomassBlob() {
|
||||
}
|
||||
|
||||
public BiomassBlob(Document document) {
|
||||
super(document);
|
||||
|
||||
biomassCount = document.getInteger("biomassCount");
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getMapInfo() {
|
||||
return MAP_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject jsonSerialise() {
|
||||
|
||||
JSONObject json = super.jsonSerialise();
|
||||
|
||||
json.put("b", biomassCount);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Document mongoSerialise() {
|
||||
|
||||
Document dbObject = super.mongoSerialise();
|
||||
|
||||
dbObject.put("biomassCount", biomassCount);
|
||||
|
||||
return dbObject;
|
||||
|
||||
}
|
||||
|
||||
public int getBiomassCount() {
|
||||
return biomassCount;
|
||||
}
|
||||
|
||||
public void setBiomassCount(int biomassCount) {
|
||||
this.biomassCount = biomassCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an object attempts to place an item in this BiomassBlob
|
||||
*
|
||||
* @return Always returns false
|
||||
*/
|
||||
@Override
|
||||
public boolean placeItem(Item item) {
|
||||
//Why would you want to place an item in a blob?
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTakeItem(int itemId) {
|
||||
return itemId == ItemBiomass.ID && biomassCount >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 it reaches 0, the plant is deleted
|
||||
*/
|
||||
@Override
|
||||
public void takeItem(int itemId) {
|
||||
|
||||
if (itemId == ItemBiomass.ID) {
|
||||
if (biomassCount > 1) {
|
||||
biomassCount--;
|
||||
} else {
|
||||
//Delete plant
|
||||
setDead(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package net.simon987.biomassplugin;
|
||||
|
||||
import net.simon987.biomassplugin.event.ObjectDeathListener;
|
||||
import net.simon987.biomassplugin.event.WorldCreationListener;
|
||||
import net.simon987.biomassplugin.event.WorldUpdateListener;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.IServerConfiguration;
|
||||
import net.simon987.server.game.objects.GameRegistry;
|
||||
import net.simon987.server.logging.LogManager;
|
||||
import net.simon987.server.plugin.ServerPlugin;
|
||||
|
||||
|
||||
public class BiomassPlugin extends ServerPlugin {
|
||||
|
||||
|
||||
@Override
|
||||
public void init(GameServer gameServer) {
|
||||
|
||||
IServerConfiguration config = gameServer.getConfig();
|
||||
GameRegistry registry = gameServer.getRegistry();
|
||||
|
||||
listeners.add(new WorldCreationListener());
|
||||
listeners.add(new WorldUpdateListener(config));
|
||||
listeners.add(new ObjectDeathListener(config));
|
||||
|
||||
registry.registerGameObject(BiomassBlob.class);
|
||||
registry.registerItem(ItemBiomass.ID, ItemBiomass.class);
|
||||
|
||||
LogManager.LOGGER.info("(BiomassPlugin) Initialised Biomass plugin");
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package net.simon987.biomassplugin;
|
||||
|
||||
import net.simon987.server.game.world.TileMap;
|
||||
import net.simon987.server.game.world.TilePlain;
|
||||
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 WorldUtils {
|
||||
|
||||
/**
|
||||
* Generate a list of biomass blobs for a world
|
||||
*/
|
||||
public static ArrayList<BiomassBlob> generateBlobs(World world, int minCount, int maxCount, int yield) {
|
||||
|
||||
Random random = new Random();
|
||||
int blobCount = random.nextInt(maxCount - minCount) + minCount;
|
||||
ArrayList<BiomassBlob> biomassBlobs = new ArrayList<>(blobCount);
|
||||
|
||||
//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
|
||||
TileMap m = world.getTileMap();
|
||||
int plainCount = 0;
|
||||
for (int y = 0; y < world.getWorldSize(); y++) {
|
||||
for (int x = 0; x < world.getWorldSize(); x++) {
|
||||
|
||||
if (m.getTileIdAt(x, y) == TilePlain.ID) {
|
||||
plainCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blobCount > plainCount) {
|
||||
blobCount = plainCount;
|
||||
}
|
||||
|
||||
outerLoop:
|
||||
for (int i = 0; i < blobCount; i++) {
|
||||
|
||||
Point p = m.getRandomTile(TilePlain.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(TilePlain.ID);
|
||||
counter++;
|
||||
|
||||
if (counter > 25) {
|
||||
continue outerLoop;
|
||||
}
|
||||
}
|
||||
|
||||
for (BiomassBlob biomassBlob : biomassBlobs) {
|
||||
if (biomassBlob.getX() == p.x && biomassBlob.getY() == p.y) {
|
||||
//There is already a blob here
|
||||
continue outerLoop;
|
||||
}
|
||||
}
|
||||
|
||||
BiomassBlob biomassBlob = new BiomassBlob();
|
||||
biomassBlob.setObjectId(new ObjectId());
|
||||
biomassBlob.setBiomassCount(yield);
|
||||
biomassBlob.setX(p.x);
|
||||
biomassBlob.setY(p.y);
|
||||
biomassBlob.setWorld(world);
|
||||
|
||||
biomassBlobs.add(biomassBlob);
|
||||
}
|
||||
}
|
||||
|
||||
return biomassBlobs;
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package net.simon987.biomassplugin.event;
|
||||
|
||||
import net.simon987.biomassplugin.BiomassBlob;
|
||||
import net.simon987.server.IServerConfiguration;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.event.GameEventListener;
|
||||
import net.simon987.server.event.ObjectDeathEvent;
|
||||
import net.simon987.server.game.objects.GameObject;
|
||||
import net.simon987.server.game.world.World;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
/**
|
||||
* Handles ObjectDeathEvent events
|
||||
*/
|
||||
public class ObjectDeathListener implements GameEventListener {
|
||||
|
||||
private int biomassDropCount;
|
||||
|
||||
public ObjectDeathListener(IServerConfiguration config) {
|
||||
biomassDropCount = config.getInt("harvester_biomass_drop_count");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getListenedEventType() {
|
||||
return ObjectDeathEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(GameEvent event) {
|
||||
|
||||
if (event.getSource().getClass().getCanonicalName().equals("net.simon987.npcplugin.HarvesterNPC")) {
|
||||
//An HarvesterNPC ObjectDeathEvent is received
|
||||
GameObject dyingHarvesterNPC = (GameObject)event.getSource();
|
||||
|
||||
//Don't spawn biomass on World border
|
||||
if (dyingHarvesterNPC.getX() != 0 && dyingHarvesterNPC.getX() != dyingHarvesterNPC.getWorld().getWorldSize() - 1 &&
|
||||
dyingHarvesterNPC.getY() != 0 && dyingHarvesterNPC.getY() != dyingHarvesterNPC.getWorld().getWorldSize() - 1) {
|
||||
//Create a new biomass
|
||||
BiomassBlob newBiomassBlob = createBiomassBlobAt(
|
||||
dyingHarvesterNPC.getX(), dyingHarvesterNPC.getY(), dyingHarvesterNPC.getWorld());
|
||||
//Add it to the world game objects
|
||||
dyingHarvesterNPC.getWorld().addObject(newBiomassBlob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a biomass at the given x, y coordinates and in the world
|
||||
* @param x x coord of biomass location
|
||||
* @param y y coord of biomass location
|
||||
* @param world world in which the biomass will be created in
|
||||
* @return the new BiomassBlob created
|
||||
*/
|
||||
private BiomassBlob createBiomassBlobAt(int x, int y, World world) {
|
||||
|
||||
BiomassBlob biomassBlob = new BiomassBlob();
|
||||
biomassBlob.setObjectId(new ObjectId());
|
||||
biomassBlob.setBiomassCount(biomassDropCount);
|
||||
biomassBlob.setX(x);
|
||||
biomassBlob.setY(y);
|
||||
biomassBlob.setWorld(world);
|
||||
|
||||
return biomassBlob;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package net.simon987.biomassplugin.event;
|
||||
|
||||
import net.simon987.biomassplugin.BiomassBlob;
|
||||
import net.simon987.biomassplugin.WorldUtils;
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.event.GameEvent;
|
||||
import net.simon987.server.event.GameEventListener;
|
||||
import net.simon987.server.event.WorldGenerationEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class WorldCreationListener implements GameEventListener {
|
||||
@Override
|
||||
public Class getListenedEventType() {
|
||||
return WorldGenerationEvent.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(GameEvent event) {
|
||||
|
||||
int minCount = GameServer.INSTANCE.getConfig().getInt("minBiomassCount");
|
||||
int maxCount = GameServer.INSTANCE.getConfig().getInt("maxBiomassCount");
|
||||
int yield = GameServer.INSTANCE.getConfig().getInt("biomass_yield");
|
||||
|
||||
ArrayList<BiomassBlob> biomassBlobs = WorldUtils.generateBlobs(((WorldGenerationEvent) event).getWorld(),
|
||||
minCount, maxCount, yield);
|
||||
|
||||
for (BiomassBlob blob : biomassBlobs) {
|
||||
((WorldGenerationEvent) event).getWorld().addObject(blob);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package net.simon987.biomassplugin.event;
|
||||
|
||||
import net.simon987.biomassplugin.BiomassBlob;
|
||||
import net.simon987.biomassplugin.WorldUtils;
|
||||
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 WorldUpdateListener implements GameEventListener {
|
||||
|
||||
private HashMap<World, Long> worldWaitMap = new HashMap<>(200);
|
||||
|
||||
private static int minBlobCount;
|
||||
private static int maxBlobCount;
|
||||
private static int blobYield;
|
||||
private static int waitTime;
|
||||
private static int blobThreshold;
|
||||
|
||||
public WorldUpdateListener(IServerConfiguration config) {
|
||||
|
||||
minBlobCount = config.getInt("minBiomassRespawnCount");
|
||||
maxBlobCount = config.getInt("maxBiomassRespawnCount");
|
||||
waitTime = config.getInt("biomassRespawnTime");
|
||||
blobThreshold = config.getInt("biomassRespawnThreshold");
|
||||
blobYield = config.getInt("biomass_yield");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getListenedEventType() {
|
||||
return WorldUpdateEvent.class;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(GameEvent event) {
|
||||
|
||||
World world = ((WorldUpdateEvent) event).getWorld();
|
||||
|
||||
if (world.getDimension().startsWith("w")) {
|
||||
//If there is less than the respawn threshold,
|
||||
if (world.findObjects(BiomassBlob.class).size() < blobThreshold) {
|
||||
|
||||
//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<BiomassBlob> newBlobs = WorldUtils.generateBlobs(world, minBlobCount,
|
||||
maxBlobCount, blobYield);
|
||||
for (BiomassBlob blob : newBlobs) {
|
||||
world.addObject(blob);
|
||||
world.incUpdatable();
|
||||
}
|
||||
|
||||
//Set the 'waitUntil' time to 0 to indicate that we are not waiting
|
||||
worldWaitMap.replace(world, 0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
4
Plugin Plant/src/main/resources/plugin.properties
Normal file
4
Plugin Plant/src/main/resources/plugin.properties
Normal file
@ -0,0 +1,4 @@
|
||||
classpath=net.simon987.biomassplugin.BiomassPlugin
|
||||
name=Biomass Plugin
|
||||
version=1.0
|
||||
depend=NPC Plugin
|
@ -1,162 +0,0 @@
|
||||
package net.simon987.plantplugin;
|
||||
|
||||
import net.simon987.server.GameServer;
|
||||
import net.simon987.server.game.GameObject;
|
||||
import net.simon987.server.game.InventoryHolder;
|
||||
import net.simon987.server.game.Updatable;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
public class Plant extends GameObject implements Updatable, InventoryHolder{
|
||||
|
||||
private static final char MAP_INFO = 0x4000;
|
||||
public static final int ID = 2;
|
||||
|
||||
/**
|
||||
* Grow time (see config.properties)
|
||||
*/
|
||||
private static final int GROW_TIME = GameServer.INSTANCE.getConfig().getInt("plant_grow_time");
|
||||
|
||||
/**
|
||||
* Game time of the creation of this Plant
|
||||
*/
|
||||
private long creationTime;
|
||||
|
||||
/**
|
||||
* Whether the plant is grown or not
|
||||
*/
|
||||
private boolean grown;
|
||||
|
||||
/**
|
||||
* Yield of the plant, in biomass units
|
||||
*/
|
||||
private int biomassCount;
|
||||
/**
|
||||
* Style of the plant (Only visual)
|
||||
*/
|
||||
private int style;
|
||||
|
||||
private static final int ITM_BIOMASS = 1;
|
||||
|
||||
@Override
|
||||
public char getMapInfo() {
|
||||
return MAP_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject serialise() {
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
json.put("type", ID);
|
||||
json.put("id", getObjectId());
|
||||
json.put("x", getX());
|
||||
json.put("y", getY());
|
||||
json.put("creationTime", creationTime);
|
||||
json.put("grown", grown);
|
||||
json.put("biomassCount", biomassCount);
|
||||
json.put("style", style);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick
|
||||
*/
|
||||
@Override
|
||||
public void update() {
|
||||
if (!grown) {
|
||||
//Check grow
|
||||
if (creationTime + GROW_TIME <= GameServer.INSTANCE.getGameUniverse().getTime()) {
|
||||
grown = true;
|
||||
biomassCount = GameServer.INSTANCE.getConfig().getInt("plant_yield");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
public void setCreationTime(long creationTime) {
|
||||
this.creationTime = creationTime;
|
||||
}
|
||||
|
||||
public boolean isGrown() {
|
||||
return grown;
|
||||
}
|
||||
|
||||
public void setGrown(boolean grown) {
|
||||
this.grown = grown;
|
||||
}
|
||||
|
||||
public int getBiomassCount() {
|
||||
return biomassCount;
|
||||
}
|
||||
|
||||
public void setBiomassCount(int biomassCount) {
|
||||
this.biomassCount = biomassCount;
|
||||
}
|
||||
|
||||
public int getStyle() {
|
||||
return style;
|
||||
}
|
||||
|
||||
public void setStyle(int style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
public static Plant deserialize(JSONObject json){
|
||||
|
||||
Plant plant = new Plant();
|
||||
|
||||
plant.setObjectId((int)(long)json.get("id"));
|
||||
plant.setX((int)(long)json.get("x"));
|
||||
plant.setY((int)(long)json.get("y"));
|
||||
plant.grown = (boolean)json.get("grown");
|
||||
plant.creationTime = (long)json.get("creationTime");
|
||||
plant.style = (int)(long)json.get("style");
|
||||
plant.biomassCount = (int)(long)json.get("biomassCount");
|
||||
|
||||
return plant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an object attempts to place an item in this Plant
|
||||
*
|
||||
* @param item item id (see MarConstants.ITEM_*)
|
||||
* @return Always returns false
|
||||
*/
|
||||
@Override
|
||||
public boolean placeItem(int item) {
|
||||
//Why would you want to place an item in a plant?
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an object attempts to take an item from this Plant.
|
||||
* If the object requests biomass, it will be subtracted from biomassCount, and
|
||||
* if it reaches 0, the plant is deleted
|
||||
*
|
||||
* @param item item id (see MarConstants.ITEM_*)
|
||||
* @return true if the requested item is ITEM_BIOMASS and if the plant is grown
|
||||
*/
|
||||
@Override
|
||||
public boolean takeItem(int item) {
|
||||
|
||||
if (item == ITM_BIOMASS) {
|
||||
if (grown && biomassCount > 1) {
|
||||
biomassCount--;
|
||||
return true;
|
||||
} else if (grown) {
|
||||
//Delete plant
|
||||
setDead(true);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
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