mirror of
https://github.com/array-in-a-matrix/brainwine.git
synced 2024-06-11 09:17:07 -04:00
Compare commits
51 commits
fb5bc94e77
...
f31cf9cc29
Author | SHA1 | Date | |
---|---|---|---|
f31cf9cc29 | |||
f89ef059a3 | |||
b7936705d3 | |||
bf3f9f314e | |||
1eda98539c | |||
261ec4e314 | |||
ab1147ba89 | |||
a58575369b | |||
4303c338a5 | |||
056e0631ac | |||
59e321292a | |||
75b1291818 | |||
5de602f0df | |||
e9a046c8ed | |||
a9ba16815f | |||
03e96be0a4 | |||
bfeb93be80 | |||
94cb2e16f8 | |||
e330b13a74 | |||
455e63f927 | |||
c444371612 | |||
882396013e | |||
1466ea0176 | |||
7a06129e8b | |||
5dbc7555de | |||
b737d46b1d | |||
34ca131f61 | |||
39f75f8322 | |||
c5ff0ba62e | |||
e7c48133cc | |||
5928ec5c98 | |||
38cf041870 | |||
20a9b5b826 | |||
188b78d5b1 | |||
9dc5cbd34f | |||
9ec3175eb1 | |||
45787c3dba | |||
df698a349b | |||
29dd9ac540 | |||
f986587ef1 | |||
dcb5e8a107 | |||
49ab4c42f4 | |||
310174864e | |||
887e235d9d | |||
2b0900b350 | |||
3bba0893b5 | |||
c6779f0f61 | |||
ac1069c3a9 | |||
81ceaa4542 | |||
8a9bc80c49 | |||
86fe6f2138 |
2
.gitattributes
vendored
2
.gitattributes
vendored
|
@ -1,3 +1,5 @@
|
|||
/gradlew text eol=lf
|
||||
|
||||
# These are explicitly windows files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
||||
|
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -32,5 +32,5 @@ jobs:
|
|||
uses: actions/upload-artifact@v3.1.1
|
||||
with:
|
||||
name: brainwine
|
||||
path: build/libs/brainwine.jar
|
||||
path: build/dist/brainwine.jar
|
||||
retention-days: 7
|
||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
|||
# Gradle
|
||||
.gradle
|
||||
build
|
||||
!**/src/**/build
|
||||
|
||||
# Eclipse
|
||||
*.launch
|
||||
|
@ -11,4 +12,4 @@ build
|
|||
bin
|
||||
|
||||
# Misc
|
||||
run
|
||||
run
|
||||
|
|
|
@ -17,7 +17,7 @@ ARG GATEWAY_PORT=5001
|
|||
ARG SERVER_PORT=5002
|
||||
ARG PORTAL_PORT=5003
|
||||
EXPOSE $GATEWAY_PORT $SERVER_PORT $PORTAL_PORT
|
||||
CMD ["sh", "-c", "java -jar /app/brainwine.jar"]
|
||||
CMD ["sh", "-c", "java -jar /app/brainwine.jar disablegui"]
|
||||
|
||||
LABEL org.opencontainers.image.title="Brainwine"
|
||||
LABEL org.opencontainers.image.description=" A portable private server for Deepworld."
|
||||
|
|
76
README.md
76
README.md
|
@ -1,39 +1,41 @@
|
|||
# Brainwine
|
||||
[![build](https://github.com/kuroppoi/brainwine/actions/workflows/build.yml/badge.svg)](https://github.com/kuroppoi/brainwine/actions)
|
||||
<h1 align="center">Brainwine</h1>
|
||||
<p align="center">
|
||||
<a href="https://github.com/kuroppoi/brainwine/actions"><img src="https://github.com/kuroppoi/brainwine/actions/workflows/build.yml/badge.svg" alt="build"/></a>
|
||||
<a href="https://github.com/kuroppoi/brainwine/releases/latest"><img src="https://img.shields.io/github/v/release/kuroppoi/brainwine?labelColor=30373D&label=Release&logoColor=959DA5&logo=github" alt="release"/></a>
|
||||
</p>
|
||||
|
||||
Brainwine is a Deepworld private server written in Java, made with user-friendliness and portability in mind.
|
||||
Due to the time it will take for this project to be complete (and my inconsistent working on it), brainwine has been prematurely open-sourced
|
||||
and is free for all to use.\
|
||||
Keep in mind, though, that this server is not finished yet. Expect to encounter bad code, bugs and missing features!\
|
||||
Brainwine is currently compatible with the following versions of Deepworld:
|
||||
- Steam: `v3.13.1`
|
||||
Brainwine is a Deepworld private server written in Java, designed to be portable and easy to use.\
|
||||
It's still a work in progress, so keep in mind that it's not yet feature-complete. (A to-do list can be found [here](https://github.com/kuroppoi/brainwine/projects/1).)\
|
||||
Brainwine currently supports the following versions of Deepworld:
|
||||
|
||||
- Windows: `v3.13.1`
|
||||
- iOS: `v2.11.0.1`
|
||||
- MacOS: `v2.11.1`
|
||||
|
||||
## Features
|
||||
A list of all planned, in-progress and finished features can be found [here.](https://github.com/kuroppoi/brainwine/projects/1)
|
||||
## Quick Local Setup
|
||||
|
||||
## Setup
|
||||
- Install [Java 8](https://adoptium.net/temurin/releases/?package=jdk&version=8).
|
||||
- Download the [latest Brainwine release](https://github.com/kuroppoi/brainwine/releases/latest).
|
||||
- Run Brainwine, go to the server tab and start the server.
|
||||
- Go to the game tab and start the game.
|
||||
- If this isn't available for you, download a [patching kit](https://github.com/kuroppoi/brainwine/releases/tag/patching-kits-1.0) for your platform and follow the instructions there.
|
||||
- Register a new account and play the game.
|
||||
|
||||
### Setting up the client
|
||||
## Building
|
||||
|
||||
Before you can connect to a server, a few modifications need to be made to the Deepworld game client.\
|
||||
The exact process of this differs per platform.\
|
||||
You may download an installation package for your desired platform [here.](https://github.com/kuroppoi/brainwine/releases/tag/patching-kits-1.0)
|
||||
### Prerequisites
|
||||
|
||||
### Setting up the server
|
||||
- Java 8 Development Kit
|
||||
|
||||
#### Prerequisites
|
||||
```sh
|
||||
git clone --recurse-submodules https://github.com/kuroppoi/brainwine.git
|
||||
cd brainwine
|
||||
./gradlew dist
|
||||
```
|
||||
|
||||
- Java 8 or newer
|
||||
The output will be located in the `/build/dist` directory.
|
||||
|
||||
You can download the latest release [here.](https://github.com/kuroppoi/brainwine/releases/latest)\
|
||||
Alternatively, if you wish to build from source, clone this repository with the `--recurse-submodules` flag\
|
||||
and run `gradlew dist` in the root directory of the repository.\
|
||||
After the build has finished, the output jar will be located in `build/libs`.\
|
||||
You may then start the server through the gui, or start it directly by running the jar with the `disablegui` flag.
|
||||
|
||||
#### Using docker
|
||||
### Using docker
|
||||
|
||||
To host brainwine using a docker you first need to build the image. On your server run the following:
|
||||
|
||||
|
@ -59,21 +61,15 @@ docker compose up
|
|||
|
||||
The server configuration files and the world data is saved in a docker volume and will accessible from `/data/` in the container. Feel free to add or remove options passed to docker or edit the compose file.
|
||||
|
||||
#### Configurations
|
||||
## Usage
|
||||
|
||||
On first-time startup, configuration files will be generated which you may modify however you like:
|
||||
- `api.json` Configuration file for news & API connectivity information.
|
||||
- `loottables.json` Configuration file for which loot may be obtained from containers.
|
||||
- `spawning.json` Configuration file for entity spawns per biome.
|
||||
- `generators` Folder containing configuration files for zone generators.
|
||||
Execute `brainwine.jar` to start the program. Navigate to the server tab and press the button to start the server.\
|
||||
It is also possible to start the server immediately with no user interface:
|
||||
|
||||
## Contributions
|
||||
```sh
|
||||
# This behavior is the default on platforms that do not support Java's Desktop API.
|
||||
java -jar brainwine.jar disablegui
|
||||
```
|
||||
|
||||
Disagree with how I did something? Found a potential error? See some room for improvement? Or just want to add a feature?
|
||||
Glad to hear it! Feel free to make a pull request anytime. Just make sure you follow the code style!
|
||||
And, apologies in advance for the lack of documentation. Haven't gotten around to do it yet. Sorry!
|
||||
|
||||
## Issues
|
||||
|
||||
Found a bug? Before posting an issue, make sure your build is up-to-date and your issue has not already been posted before.
|
||||
Provide a detailed explanation of the issue, and how to reproduce it. I'll get to it ASAP!
|
||||
To connect to a local or remote server, download a [patching kit](https://github.com/kuroppoi/brainwine/releases/tag/patching-kits-1.0) for your desired platform.\
|
||||
Alternatively, Windows users may use the program's user interface to configure the host settings and start the game.
|
||||
|
|
|
@ -8,9 +8,5 @@ repositories {
|
|||
|
||||
dependencies {
|
||||
implementation 'io.javalin:javalin:4.6.8'
|
||||
implementation project(':shared')
|
||||
}
|
||||
|
||||
jar {
|
||||
archiveBaseName = 'brainwine-api'
|
||||
implementation project(':brainwine-shared')
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ public interface DataFetcher {
|
|||
public boolean isPlayerNameTaken(String name);
|
||||
public String registerPlayer(String name);
|
||||
public String login(String name, String password);
|
||||
public String fetchPlayerName(String name);
|
||||
public boolean verifyAuthToken(String name, String token);
|
||||
public boolean verifyApiToken(String apiToken);
|
||||
public Collection<ZoneInfo> fetchZoneInfo();
|
||||
|
|
|
@ -23,6 +23,11 @@ public class DefaultDataFetcher implements DataFetcher {
|
|||
throw exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fetchPlayerName(String name) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyAuthToken(String name, String token) {
|
||||
throw exception;
|
||||
|
|
|
@ -111,7 +111,7 @@ public class GatewayService {
|
|||
return;
|
||||
}
|
||||
|
||||
ctx.json(new ServerConnectInfo(api.getGameServerHost(), name, token));
|
||||
ctx.json(new ServerConnectInfo(api.getGameServerHost(), dataFetcher.fetchPlayerName(name), token));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
28
build-logic/build.gradle
Normal file
28
build-logic/build.gradle
Normal file
|
@ -0,0 +1,28 @@
|
|||
plugins {
|
||||
id 'java-gradle-plugin'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
boot {
|
||||
|
||||
}
|
||||
main {
|
||||
compileClasspath += sourceSets.boot.output
|
||||
runtimeClasspath += sourceSets.boot.output
|
||||
}
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
distributionPlugin {
|
||||
id = "brainwine.distribution"
|
||||
implementationClass = "brainwine.build.DistributionPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
from sourceSets.boot.output
|
||||
}
|
||||
|
||||
version = '1.0.0-SNAPSHOT'
|
84
build-logic/src/boot/java/brainwine/bootstrap/Bootstrap.java
Normal file
84
build-logic/src/boot/java/brainwine/bootstrap/Bootstrap.java
Normal file
|
@ -0,0 +1,84 @@
|
|||
package brainwine.bootstrap;
|
||||
|
||||
import static brainwine.bootstrap.Constants.BOOT_CLASS_KEY;
|
||||
import static brainwine.bootstrap.Constants.CLASS_PATH_KEY;
|
||||
import static brainwine.bootstrap.Constants.LIBRARY_PATH;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
public class Bootstrap {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Bootstrap().run(args);
|
||||
}
|
||||
|
||||
private void run(String[] args) {
|
||||
Attributes attributes = null;
|
||||
|
||||
try {
|
||||
Enumeration<URL> resources = getClass().getClassLoader().getResources(JarFile.MANIFEST_NAME);
|
||||
|
||||
while(resources.hasMoreElements()) {
|
||||
try(InputStream inputStream = resources.nextElement().openStream()) {
|
||||
Manifest manifest = new Manifest(inputStream);
|
||||
if(getClass().getName().equals(manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS))) {
|
||||
attributes = manifest.getMainAttributes();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(IOException e) {
|
||||
System.err.println("Could not load manifest file");
|
||||
e.printStackTrace();
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
String[] libraryNames = attributes.getValue(CLASS_PATH_KEY).split(";");
|
||||
URL[] libraryUrls = new URL[libraryNames.length];
|
||||
|
||||
try {
|
||||
for(int i = 0; i < libraryNames.length; i++) {
|
||||
String libraryName = libraryNames[i];
|
||||
|
||||
try(InputStream inputStream = getClass().getResourceAsStream(String.format("/%s/%s", LIBRARY_PATH, libraryName))) {
|
||||
File outputFile = new File("libraries", libraryName);
|
||||
libraryUrls[i] = outputFile.toURI().toURL();
|
||||
|
||||
if(outputFile.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
outputFile.getParentFile().mkdirs();
|
||||
Files.copy(inputStream, outputFile.toPath());
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
System.err.println("Could not extract library JARs");
|
||||
e.printStackTrace();
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
URLClassLoader classLoader = new URLClassLoader(libraryUrls, getClass().getClassLoader().getParent());
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
|
||||
try {
|
||||
Class<?> mainClass = Class.forName(attributes.getValue(BOOT_CLASS_KEY), true, classLoader);
|
||||
Method method = mainClass.getMethod("main", String[].class);
|
||||
method.invoke(null, (Object)args);
|
||||
} catch(ReflectiveOperationException e) {
|
||||
System.err.println("Could not invoke entry point");
|
||||
e.printStackTrace();
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
12
build-logic/src/boot/java/brainwine/bootstrap/Constants.java
Normal file
12
build-logic/src/boot/java/brainwine/bootstrap/Constants.java
Normal file
|
@ -0,0 +1,12 @@
|
|||
package brainwine.bootstrap;
|
||||
|
||||
import java.util.jar.Attributes;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final Attributes.Name BOOT_CLASS_KEY = new Attributes.Name("Dist-Boot-Class");
|
||||
public static final Attributes.Name CLASS_PATH_KEY = new Attributes.Name("Dist-Class-Path");
|
||||
public static final String LICENSE_PATH = "META-INF/LICENSE";
|
||||
public static final String LIBRARY_PATH = "META-INF/libraries";
|
||||
public static final Class<?> MAIN_CLASS = Bootstrap.class;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package brainwine.build;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
|
||||
public class DistributionPlugin implements Plugin<Project> {
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
project.getPlugins().apply(JavaPlugin.class);
|
||||
project.getTasks().register("dist", DistributionTask.class, task -> task.dependsOn("build"));
|
||||
}
|
||||
}
|
128
build-logic/src/main/java/brainwine/build/DistributionTask.java
Normal file
128
build-logic/src/main/java/brainwine/build/DistributionTask.java
Normal file
|
@ -0,0 +1,128 @@
|
|||
package brainwine.build;
|
||||
|
||||
import static brainwine.bootstrap.Constants.BOOT_CLASS_KEY;
|
||||
import static brainwine.bootstrap.Constants.CLASS_PATH_KEY;
|
||||
import static brainwine.bootstrap.Constants.LIBRARY_PATH;
|
||||
import static brainwine.bootstrap.Constants.LICENSE_PATH;
|
||||
import static brainwine.bootstrap.Constants.MAIN_CLASS;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.file.FileTree;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.initialization.IncludedBuild;
|
||||
import org.gradle.api.invocation.Gradle;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.api.tasks.bundling.Jar;
|
||||
|
||||
public abstract class DistributionTask extends DefaultTask {
|
||||
|
||||
private final FileTree bootCodeTree;
|
||||
|
||||
@Input
|
||||
public abstract Property<String> getMainClass();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public abstract Property<String> getArchiveFileName();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public abstract RegularFileProperty getLicenseFile();
|
||||
|
||||
@Inject
|
||||
public DistributionTask(Gradle gradle) {
|
||||
IncludedBuild build = gradle.getIncludedBuilds().stream().filter(x -> x.getName().equals("build-logic")).findFirst().get();
|
||||
bootCodeTree = getProject().fileTree(new File(build.getProjectDir(), "build/classes/java/boot"));
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void createDistributionArchive() throws IOException {
|
||||
Configuration config = getProject().getConfigurations().getByName("runtimeClasspath");
|
||||
Jar jarTask = (Jar)getProject().getTasks().getByName("jar");
|
||||
String archiveFileName = getArchiveFileName().getOrElse(jarTask.getArchiveFileName().get());
|
||||
File outputDirectory = new File(getProject().getBuildDir(), "dist");
|
||||
outputDirectory.mkdirs();
|
||||
File outputFile = new File(outputDirectory, archiveFileName);
|
||||
|
||||
// Fetch libraries
|
||||
List<File> classpath = new ArrayList<>();
|
||||
config.getResolvedConfiguration().getResolvedArtifacts().forEach(artifact -> classpath.add(artifact.getFile()));
|
||||
jarTask.getOutputs().getFiles().forEach(classpath::add);
|
||||
classpath.sort((a, b) -> a.getName().compareTo(b.getName())); // Guarantee file order
|
||||
|
||||
// Create jar manifest
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
||||
manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, MAIN_CLASS.getName());
|
||||
manifest.getMainAttributes().put(BOOT_CLASS_KEY, getMainClass().get());
|
||||
manifest.getMainAttributes().put(CLASS_PATH_KEY, String.join(";", classpath.stream().map(File::getName).collect(Collectors.toList())));
|
||||
manifest.getMainAttributes().putValue("Multi-Release", "true");
|
||||
|
||||
// Create jar file
|
||||
try(JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(outputFile))) {
|
||||
// Add manifest
|
||||
addJarManifest(outputStream, manifest);
|
||||
|
||||
// Add libraries
|
||||
for(File file : classpath) {
|
||||
addFileToJar(outputStream, file, String.format("%s/%s", LIBRARY_PATH, file.getName()));
|
||||
}
|
||||
|
||||
// Add boot code
|
||||
bootCodeTree.visit(details -> {
|
||||
if(!details.isDirectory()) {
|
||||
try {
|
||||
addFileToJar(outputStream, details.getFile(), details.getPath());
|
||||
} catch(IOException e) {
|
||||
throw new GradleException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add license
|
||||
RegularFileProperty licenseFile = getLicenseFile();
|
||||
|
||||
if(licenseFile.isPresent()) {
|
||||
addFileToJar(outputStream, licenseFile.get().getAsFile(), LICENSE_PATH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addJarManifest(JarOutputStream outputStream, Manifest manifest) throws IOException {
|
||||
JarEntry entry = new JarEntry(JarFile.MANIFEST_NAME);
|
||||
entry.setTime(0);
|
||||
outputStream.putNextEntry(entry);
|
||||
manifest.write(outputStream);
|
||||
outputStream.closeEntry();
|
||||
}
|
||||
|
||||
private void addFileToJar(JarOutputStream outputStream, File file, String targetPath) throws IOException {
|
||||
byte[] bytes = Files.readAllBytes(file.toPath());
|
||||
JarEntry entry = new JarEntry(targetPath);
|
||||
entry.setTime(0);
|
||||
entry.setSize(bytes.length);
|
||||
outputStream.putNextEntry(entry);
|
||||
outputStream.write(bytes);
|
||||
outputStream.closeEntry();
|
||||
}
|
||||
}
|
28
build.gradle
28
build.gradle
|
@ -1,9 +1,9 @@
|
|||
plugins {
|
||||
id 'java'
|
||||
id 'brainwine.distribution'
|
||||
}
|
||||
|
||||
ext {
|
||||
mainClass = 'brainwine.Bootstrap'
|
||||
mainClass = 'brainwine.Main'
|
||||
workingDirectory = 'run'
|
||||
}
|
||||
|
||||
|
@ -15,26 +15,14 @@ dependencies {
|
|||
implementation 'com.formdev:flatlaf-intellij-themes:3.0'
|
||||
implementation 'com.formdev:flatlaf-extras:3.0'
|
||||
implementation 'com.formdev:flatlaf:3.0'
|
||||
implementation project(':api')
|
||||
implementation project(':gameserver')
|
||||
implementation project(':shared')
|
||||
implementation project(':brainwine-api')
|
||||
implementation project(':brainwine-gameserver')
|
||||
implementation project(':brainwine-shared')
|
||||
}
|
||||
|
||||
task dist(type: Jar) {
|
||||
manifest {
|
||||
attributes 'Multi-Release': 'true',
|
||||
'Main-Class': project.ext.mainClass
|
||||
}
|
||||
|
||||
from {
|
||||
configurations.runtimeClasspath.collect {
|
||||
it.isDirectory() ? it : zipTree(it)
|
||||
}
|
||||
}
|
||||
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
dependsOn configurations.runtimeClasspath
|
||||
with jar
|
||||
dist {
|
||||
mainClass = project.ext.mainClass
|
||||
licenseFile = file("${project.rootDir}/LICENSE.md")
|
||||
}
|
||||
|
||||
task run(type: JavaExec) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit ec2749d94b86dbbdefa52e0146ce278688e28370
|
||||
Subproject commit 6052c53944e3d4469819e725c59914ea136b2007
|
|
@ -24,11 +24,7 @@ dependencies {
|
|||
implementation 'org.reflections:reflections:0.10.2'
|
||||
implementation 'io.netty:netty-all:4.1.79.Final'
|
||||
implementation 'org.mindrot:jbcrypt:0.4'
|
||||
implementation project(':shared')
|
||||
}
|
||||
|
||||
jar {
|
||||
archiveBaseName = 'brainwine-gameserver'
|
||||
implementation project(':brainwine-shared')
|
||||
}
|
||||
|
||||
processResources.includeEmptyDirs = false
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.yaml.snakeyaml.Yaml;
|
|||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
import brainwine.gameserver.command.CommandManager;
|
||||
import brainwine.gameserver.commands.CommandManager;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.entity.player.Skill;
|
||||
import brainwine.gameserver.item.Item;
|
||||
|
|
|
@ -9,8 +9,8 @@ import org.apache.logging.log4j.LogManager;
|
|||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import brainwine.gameserver.achievements.AchievementManager;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.command.CommandManager;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.commands.CommandManager;
|
||||
import brainwine.gameserver.entity.EntityRegistry;
|
||||
import brainwine.gameserver.entity.player.NotificationType;
|
||||
import brainwine.gameserver.entity.player.PlayerManager;
|
||||
|
|
117
gameserver/src/main/java/brainwine/gameserver/Naming.java
Normal file
117
gameserver/src/main/java/brainwine/gameserver/Naming.java
Normal file
|
@ -0,0 +1,117 @@
|
|||
package brainwine.gameserver;
|
||||
|
||||
/**
|
||||
* TODO all I'm doing here is moving the problem somewhere else.
|
||||
*
|
||||
* Entity names are sourced from: https://github.com/bytebin/deepworld-gameserver/blob/master/config/fake.yml
|
||||
*/
|
||||
public class Naming {
|
||||
|
||||
private static final String[] ZONE_FIRST_NAMES = {
|
||||
"Malvern", "Tralee", "Horncastle", "Old", "Westwood",
|
||||
"Citta", "Tadley", "Mossley", "West", "East",
|
||||
"North", "South", "Wadpen", "Githam", "Soatnust",
|
||||
"Highworth", "Creakynip", "Upper", "Lower", "Cannock",
|
||||
"Dovercourt", "Limerick", "Pickering", "Glumshed", "Crusthack",
|
||||
"Osyltyr", "Aberstaple", "New", "Stroud", "Crumclum",
|
||||
"Crumsidle", "Bankswund", "Fiddletrast", "Bournpan", "St.",
|
||||
"Funderbost", "Bexwoddly", "Pilkingheld", "Wittlepen", "Rabbitbleaker",
|
||||
"Griffingumby", "Guilthead", "Bigglelund", "Bunnymold", "Rosesidle",
|
||||
"Crushthorn", "Tanlyward", "Ahncrace", "Pilkingking", "Dingstrath",
|
||||
"Axebury", "Ginglingtap", "Ballybibby", "Shadehoven"
|
||||
};
|
||||
|
||||
private static final String[] ZONE_LAST_NAMES = {
|
||||
"Falls", "Alloa", "Glen", "Way", "Dolente",
|
||||
"Peak", "Heights", "Creek", "Banffshire", "Chagford",
|
||||
"Gorge", "Valley", "Catacombs", "Depths", "Mines",
|
||||
"Crickbridge", "Guildbost", "Pits", "Vaults", "Ruins",
|
||||
"Dell", "Keep", "Chatterdin", "Scrimmance", "Gitwick",
|
||||
"Ridge", "Alresford", "Place", "Bridge", "Glade",
|
||||
"Mill", "Court", "Dooftory", "Hills", "Specklewint",
|
||||
"Grove", "Aylesbury", "Wagwouth", "Russetcumby", "Point",
|
||||
"Canyon", "Cranwarry", "Bluff", "Passage", "Crantippy",
|
||||
"Kerbodome", "Dale", "Cemetery"
|
||||
};
|
||||
|
||||
public static final String[] ENTITY_FIRST_NAMES = {
|
||||
"Aaron", "Abby", "Abigale", "Abraham", "Ada", "Adella", "Agnes", "Alan",
|
||||
"Albert", "Alexander", "Allie", "Almira", "Almyra", "Alonzo", "Alva", "Ambrose",
|
||||
"Amelia", "Amon", "Amos", "Andrew", "Ann", "Annie", "Aquilla", "Archibald",
|
||||
"Arnold", "Arrah", "Asa", "Augustus", "Barnabas", "Bartholomew", "Beatrice", "Becky",
|
||||
"Benedict", "Benjamin", "Bennet", "Bernard", "Bernice", "Bertram", "Bess", "Bessie",
|
||||
"Beth", "Betsy", "Buford", "Byron", "Calvin", "Charity", "Charles", "Charlotte",
|
||||
"Chastity", "Christopher", "Claire", "Clarence", "Clement", "Clinton", "Cole", "Columbus",
|
||||
"Commodore Perry", "Constance", "Cynthia", "Daniel", "David", "Dick", "Dorothy", "Edith",
|
||||
"Edmund", "Edna", "Edward", "Edwin", "Edwina", "Eldon", "Eleanor", "Eli",
|
||||
"Elijah", "Eliza", "Elizabeth", "Ella", "Ellie", "Elvira", "Emma", "Emmett",
|
||||
"Enoch", "Esther", "Ethel", "Ettie", "Eudora", "Eva", "Ezekiel", "Ezra",
|
||||
"Fanny", "Fidelia", "Flora", "Florence", "Frances", "Francis", "Franklin", "Frederick",
|
||||
"Gabriel", "Garrett", "Geneve", "Genevieve", "George", "George", "Georgia", "Gertie",
|
||||
"Gertrude", "Gideon", "Gilbert", "Ginny", "Gladys", "Grace", "Granville", "Hannah",
|
||||
"Harland", "Harold", "Harrison", "Harvey", "Hattie", "Helen", "Helene", "Henrietta",
|
||||
"Henry", "Hester", "Hettie", "Hiram", "Hope", "Horace", "Horatio", "Hortence",
|
||||
"Hugh", "Isaac", "Isaac Newton", "Isabella", "Isaiah", "Israel", "Jacob", "James",
|
||||
"Jane", "Jasper", "Jedediah", "Jefferson", "Jennie", "Jeptha", "Jessamine", "Jesse",
|
||||
"Joel", "John Paul", "John Wesley", "Jonathan", "Joseph", "Josephine", "Josephus", "Joshua",
|
||||
"Josiah", "Judith", "Julia", "Julian", "Juliet", "Julius", "Katherine", "Lafayette",
|
||||
"Laura", "Lawrence", "Leah", "Leander", "Lenora", "Les", "Letitia", "Levi",
|
||||
"Levi", "Lewis", "Lila", "Lilly", "Liza", "Lorena", "Lorraine", "Lottie",
|
||||
"Louis", "Louisa", "Louise", "Lucas", "Lucas", "Lucian", "Lucian", "Lucius",
|
||||
"Lucius", "Lucy", "Luke", "Luke", "Lulu", "Luther", "Luther", "Lydia",
|
||||
"Mahulda", "Marcellus", "Margaret", "Mark", "Martha", "Martin", "Mary", "Mary Elizabeth",
|
||||
"Mary Frances", "Masheck", "Matilda", "Matthew", "Maude", "Maurice", "Maxine", "Maxwell",
|
||||
"Mercy", "Meriwether", "Meriwether Lewis", "Merrill", "Mildred", "Minerva", "Missouri", "Molly",
|
||||
"Mordecai", "Morgan", "Morris", "Myrtle", "Nancy", "Natalie", "Nathaniel", "Ned",
|
||||
"Nellie", "Nettie", "Newton", "Nicholas", "Nimrod", "Ninian", "Nora", "Obediah",
|
||||
"Octavius", "Orpha", "Orville", "Oscar", "Owen", "Parthena", "Patrick", "Patrick Henry",
|
||||
"Patsy", "Paul", "Paul", "Peggy", "Permelia", "Perry", "Peter", "Philomena",
|
||||
"Phoebe", "Pleasant", "Polly", "Preshea", "Rachel", "Ralph", "Raymond", "Rebecca",
|
||||
"Reuben", "Rhoda", "Richard", "Robert", "Robert Lee", "Roderick", "Rowena", "Rudolph",
|
||||
"Rufina", "Rufus", "Ruth", "Sally", "Sam Houston", "Samantha", "Samuel", "Sarah",
|
||||
"Sarah Ann", "Sarah Elizabeth", "Savannah", "Selina", "Seth", "Silas", "Simeon", "Simon",
|
||||
"Sophronia", "Stanley", "Stella", "Stephen", "Thaddeus", "Theodore", "Theodosia", "Thomas",
|
||||
"Timothy", "Ulysses", "Uriah", "Vertiline", "Victor", "Victoria", "Virginia", "Vivian",
|
||||
"Walter", "Warren", "Washington", "Wilfred", "William", "Winnifred", "Zachariah", "Zebulon",
|
||||
"Zedock", "Zona", "Zylphia"
|
||||
};
|
||||
|
||||
public static final String[] ENTITY_LAST_NAMES = {
|
||||
"Abraham", "Adams", "Alcorn", "Alderdice", "Angus", "Ashdown", "Ayre", "Backhaus",
|
||||
"Baldwin", "Bamford", "Beaton", "Blackwood", "Blair", "Blewett", "Bornholdt", "Bowden",
|
||||
"Burrows", "Cameron", "Carroll", "Clarke", "Claxton", "Collins", "Colson", "Connor",
|
||||
"Conroy", "Cullen", "Cunningham", "Curd", "Curnow", "Cusack", "Dagon", "Dalton",
|
||||
"Dawes", "Desmond", "Dewar", "Dickenson", "Donnell", "Drummond", "Dunstan", "English",
|
||||
"Eveans", "Faraday", "Faulkner", "Fitzgerald", "Fitzpatrick", "Fletcher", "Foster", "Franklin",
|
||||
"Fulton", "Gallagher", "Gibbons", "Gilmore", "Glover", "Goodfellow", "Goodwin", "Griffiths",
|
||||
"Gullifer", "Hadley", "Haeffner", "Hanlon", "Harding", "Harris", "Holloway", "Hughes",
|
||||
"Jarvis", "Jefferies", "Johnstone", "Kaylock", "Keane", "Kemp", "Kernaghan", "Kirby",
|
||||
"Kirkland", "Knight", "LaFontaine", "Lawford", "Lawrence", "Lennox", "Longley", "Lonsdale",
|
||||
"Luckett", "Lyons", "Macklin", "Madill", "Marsden", "Marshall", "Martin", "Mather",
|
||||
"Mathieson", "Maunder", "McColl", "McDermott", "McGillicuddy", "McKenzie", "McLachlan", "McNeil",
|
||||
"Meaklim", "Meighan", "Mellor", "Meyers", "Milsom", "Mitchell", "Mitchelson", "Moore",
|
||||
"Morgan", "Morrison", "Mortimer", "Moulsdale", "Murphy", "Nelson", "Nolan", "Noonan",
|
||||
"O'Keefe", "O'Sullivan", "Palmer", "Parnell", "Pattison", "Pettit", "Phillips", "Pinner",
|
||||
"Porter", "Prosser", "Ramseyer", "Renton", "Rickard", "Riddington", "Roche", "Rowe",
|
||||
"Russell", "Salisbury", "Saunders", "Sawyer", "Scanlan", "Scarborough", "Schwarer", "Sheary",
|
||||
"Sheedy", "Shelton", "Shields", "Shinnick", "Skinner", "Sommer", "Spencer", "Stanbury",
|
||||
"Stanton", "Storey", "Swaisbrick", "Thorley", "Thumpston", "Tichborne", "Tinning", "Tobin",
|
||||
"Todd", "Trimble", "Twomey", "Upton", "Urwin", "Vandenburg", "Vinge", "Wakefield",
|
||||
"Wakenshaw", "Walden", "Wallace", "Walton", "Warner", "Webb", "Whitehill", "Wickes",
|
||||
"Wilberforce", "Wilkinson", "Wolstenholme", "Wright"
|
||||
};
|
||||
|
||||
public static String getRandomZoneName() {
|
||||
return getRandomName(ZONE_FIRST_NAMES, ZONE_LAST_NAMES);
|
||||
}
|
||||
|
||||
public static String getRandomEntityName() {
|
||||
return getRandomName(ENTITY_FIRST_NAMES, ENTITY_LAST_NAMES);
|
||||
}
|
||||
|
||||
private static String getRandomName(String[] firstNames, String[] lastNames) {
|
||||
String firstName = firstNames[(int)(Math.random() * firstNames.length)];
|
||||
String lastName = lastNames[(int)(Math.random() * lastNames.length)];
|
||||
return firstName + " " + lastName;
|
||||
}
|
||||
}
|
42
gameserver/src/main/java/brainwine/gameserver/Timer.java
Normal file
42
gameserver/src/main/java/brainwine/gameserver/Timer.java
Normal file
|
@ -0,0 +1,42 @@
|
|||
package brainwine.gameserver;
|
||||
|
||||
/**
|
||||
* Model for synchronous timers.
|
||||
*/
|
||||
public class Timer<T> {
|
||||
|
||||
private T key;
|
||||
private long time;
|
||||
private Runnable action;
|
||||
|
||||
public Timer(T key, long delay, Runnable action) {
|
||||
this.key = key;
|
||||
this.time = System.currentTimeMillis() + delay;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public boolean process() {
|
||||
return process(false);
|
||||
}
|
||||
|
||||
public boolean process(boolean force) {
|
||||
if(force || System.currentTimeMillis() >= time) {
|
||||
action.run();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public T getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public Runnable getAction() {
|
||||
return action;
|
||||
}
|
||||
}
|
|
@ -28,6 +28,8 @@ import brainwine.gameserver.util.MathUtils;
|
|||
@Type(name = "ScavengingAchievement", value = ScavengingAchievement.class),
|
||||
@Type(name = "DiscoveryAchievement", value = DiscoveryAchievement.class),
|
||||
@Type(name = "SpawnerStoppageAchievement", value = SpawnerStoppageAchievement.class),
|
||||
@Type(name = "UndertakerAchievement", value = UndertakerAchievement.class),
|
||||
@Type(name = "TrappingAchievement", value = TrappingAchievement.class),
|
||||
@Type(name = "Journeyman", value = JourneymanAchievement.class)
|
||||
})
|
||||
@JsonSerialize(using = AchievementSerializer.class)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package brainwine.gameserver.achievements;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
public class TrappingAchievement extends Achievement {
|
||||
|
||||
@JsonCreator
|
||||
public TrappingAchievement(@JacksonInject("title") String title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProgress(Player player) {
|
||||
return player.getStatistics().getTotalTrappings();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package brainwine.gameserver.achievements;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
public class UndertakerAchievement extends Achievement {
|
||||
|
||||
@JsonCreator
|
||||
public UndertakerAchievement(@JacksonInject("title") String title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProgress(Player player) {
|
||||
return player.getStatistics().getUndertakings();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package brainwine.gameserver.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CommandInfo {
|
||||
|
||||
public String name();
|
||||
public String description();
|
||||
public String[] aliases() default {};
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package brainwine.gameserver.command;
|
||||
|
||||
public abstract class Command {
|
||||
|
||||
public abstract void execute(CommandExecutor executor, String[] args);
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public String[] getAliases() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "No description for this command";
|
||||
}
|
||||
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/" + getName();
|
||||
}
|
||||
|
||||
public boolean canExecute(CommandExecutor executor) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,182 +0,0 @@
|
|||
package brainwine.gameserver.command;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
import static brainwine.shared.LogMarkers.SERVER_MARKER;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import brainwine.gameserver.command.commands.AcidityCommand;
|
||||
import brainwine.gameserver.command.commands.AdminCommand;
|
||||
import brainwine.gameserver.command.commands.BanCommand;
|
||||
import brainwine.gameserver.command.commands.BroadcastCommand;
|
||||
import brainwine.gameserver.command.commands.EntityCommand;
|
||||
import brainwine.gameserver.command.commands.ExperienceCommand;
|
||||
import brainwine.gameserver.command.commands.ExportCommand;
|
||||
import brainwine.gameserver.command.commands.GenerateZoneCommand;
|
||||
import brainwine.gameserver.command.commands.GiveCommand;
|
||||
import brainwine.gameserver.command.commands.HealthCommand;
|
||||
import brainwine.gameserver.command.commands.HelpCommand;
|
||||
import brainwine.gameserver.command.commands.ImportCommand;
|
||||
import brainwine.gameserver.command.commands.KickCommand;
|
||||
import brainwine.gameserver.command.commands.LevelCommand;
|
||||
import brainwine.gameserver.command.commands.MuteCommand;
|
||||
import brainwine.gameserver.command.commands.PlayerIdCommand;
|
||||
import brainwine.gameserver.command.commands.PositionCommand;
|
||||
import brainwine.gameserver.command.commands.PrefabListCommand;
|
||||
import brainwine.gameserver.command.commands.RegisterCommand;
|
||||
import brainwine.gameserver.command.commands.RickrollCommand;
|
||||
import brainwine.gameserver.command.commands.SayCommand;
|
||||
import brainwine.gameserver.command.commands.SeedCommand;
|
||||
import brainwine.gameserver.command.commands.SettleLiquidsCommand;
|
||||
import brainwine.gameserver.command.commands.SkillPointsCommand;
|
||||
import brainwine.gameserver.command.commands.StopCommand;
|
||||
import brainwine.gameserver.command.commands.TeleportCommand;
|
||||
import brainwine.gameserver.command.commands.ThinkCommand;
|
||||
import brainwine.gameserver.command.commands.TimeCommand;
|
||||
import brainwine.gameserver.command.commands.UnbanCommand;
|
||||
import brainwine.gameserver.command.commands.UnmuteCommand;
|
||||
import brainwine.gameserver.command.commands.WeatherCommand;
|
||||
import brainwine.gameserver.command.commands.ZoneIdCommand;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
public class CommandManager {
|
||||
|
||||
public static final String CUSTOM_COMMAND_PREFIX = "!"; // TODO configurable
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
private static final Map<String, Command> commands = new HashMap<>();
|
||||
private static final Map<String, Command> aliases = new HashMap<>();
|
||||
private static boolean initialized = false;
|
||||
|
||||
public static void init() {
|
||||
if(initialized) {
|
||||
logger.warn(SERVER_MARKER, "CommandManager is already initialized - skipping!");
|
||||
return;
|
||||
}
|
||||
|
||||
registerCommands();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
private static void registerCommands() {
|
||||
logger.info(SERVER_MARKER, "Registering commands ...");
|
||||
registerCommand(new StopCommand());
|
||||
registerCommand(new RegisterCommand());
|
||||
registerCommand(new TeleportCommand());
|
||||
registerCommand(new KickCommand());
|
||||
registerCommand(new MuteCommand());
|
||||
registerCommand(new UnmuteCommand());
|
||||
registerCommand(new BanCommand());
|
||||
registerCommand(new UnbanCommand());
|
||||
registerCommand(new SayCommand());
|
||||
registerCommand(new ThinkCommand());
|
||||
registerCommand(new BroadcastCommand());
|
||||
registerCommand(new PlayerIdCommand());
|
||||
registerCommand(new ZoneIdCommand());
|
||||
registerCommand(new AdminCommand());
|
||||
registerCommand(new HelpCommand());
|
||||
registerCommand(new GiveCommand());
|
||||
registerCommand(new GenerateZoneCommand());
|
||||
registerCommand(new SeedCommand());
|
||||
registerCommand(new PrefabListCommand());
|
||||
registerCommand(new ExportCommand());
|
||||
registerCommand(new ImportCommand());
|
||||
registerCommand(new PositionCommand());
|
||||
registerCommand(new RickrollCommand());
|
||||
registerCommand(new EntityCommand());
|
||||
registerCommand(new HealthCommand());
|
||||
registerCommand(new ExperienceCommand());
|
||||
registerCommand(new LevelCommand());
|
||||
registerCommand(new SkillPointsCommand());
|
||||
registerCommand(new SettleLiquidsCommand());
|
||||
registerCommand(new WeatherCommand());
|
||||
registerCommand(new AcidityCommand());
|
||||
registerCommand(new TimeCommand());
|
||||
}
|
||||
|
||||
public static void executeCommand(CommandExecutor executor, String commandLine) {
|
||||
if(commandLine.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
commandLine.trim().replaceAll(" +", " ");
|
||||
String[] sections = commandLine.split(" ", 2);
|
||||
|
||||
if(sections.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String name = sections[0];
|
||||
String[] args = sections.length > 1 ? sections[1].split(" ") : new String[0];
|
||||
executeCommand(executor, name, args);
|
||||
}
|
||||
|
||||
public static void executeCommand(CommandExecutor executor, String commandName, String[] args) {
|
||||
if(!(executor instanceof Player) && commandName.startsWith(CUSTOM_COMMAND_PREFIX) || commandName.startsWith("/")) {
|
||||
commandName = commandName.substring(1);
|
||||
}
|
||||
|
||||
Command command = getCommand(commandName, true);
|
||||
|
||||
if(command == null || !command.canExecute(executor)) {
|
||||
executor.notify("Unknown command. Type '/help' for a list of commands.", SYSTEM);
|
||||
return;
|
||||
}
|
||||
|
||||
if(executor instanceof Player) {
|
||||
Player player = (Player)executor;
|
||||
logger.info(SERVER_MARKER, "{} used command '/{}'", player.getName(), commandName + (args.length == 0 ? "" : " " + String.join(" ", args)));
|
||||
}
|
||||
|
||||
command.execute(executor, args);
|
||||
}
|
||||
|
||||
public static void registerCommand(Command command) {
|
||||
String name = command.getName();
|
||||
|
||||
if(commands.containsKey(name)) {
|
||||
logger.warn(SERVER_MARKER, "Attempted to register duplicate command {} with name {}", command.getClass(), name);
|
||||
return;
|
||||
}
|
||||
|
||||
commands.put(name, command);
|
||||
String[] aliases = command.getAliases();
|
||||
|
||||
if(aliases != null) {
|
||||
for(String alias : aliases) {
|
||||
if(commands.containsKey(alias) || CommandManager.aliases.containsKey(alias)) {
|
||||
logger.warn(SERVER_MARKER, "Duplicate alias {} for command {}", alias, command.getClass());
|
||||
continue;
|
||||
}
|
||||
|
||||
CommandManager.aliases.put(alias, command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getCommandNames() {
|
||||
Set<String> names = new HashSet<>();
|
||||
names.addAll(commands.keySet());
|
||||
names.addAll(aliases.keySet());
|
||||
return names;
|
||||
}
|
||||
|
||||
public static Command getCommand(String name) {
|
||||
return getCommand(name, false);
|
||||
}
|
||||
|
||||
public static Command getCommand(String name, boolean allowAlias) {
|
||||
return commands.getOrDefault(name, allowAlias ? aliases.get(name) : null);
|
||||
}
|
||||
|
||||
public static Collection<Command> getCommands() {
|
||||
return Collections.unmodifiableCollection(commands.values());
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.entity.EntityConfig;
|
||||
import brainwine.gameserver.entity.EntityRegistry;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.player.NotificationType;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
|
||||
public class EntityCommand extends Command {
|
||||
|
||||
@Override
|
||||
public void execute(CommandExecutor executor, String[] args) {
|
||||
if(args.length == 0) {
|
||||
executor.notify(String.format("Usage: %s", getUsage(executor)), SYSTEM);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player)executor;
|
||||
String name = args[0];
|
||||
EntityConfig config = EntityRegistry.getEntityConfig(name);
|
||||
|
||||
if(config == null) {
|
||||
executor.notify(String.format("Entity with name '%s' does not exist.", name), NotificationType.SYSTEM);
|
||||
return;
|
||||
}
|
||||
|
||||
Zone zone = player.getZone();
|
||||
zone.spawnEntity(new Npc(zone, config), (int)player.getX(), (int)player.getY(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "entity";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Spawns an entity at your current location.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/entity <name>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(CommandExecutor executor) {
|
||||
return executor.isAdmin() && executor instanceof Player;
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.server.messages.EventMessage;
|
||||
|
||||
public class RickrollCommand extends Command {
|
||||
|
||||
@Override
|
||||
public void execute(CommandExecutor executor, String[] args) {
|
||||
if(args.length < 1) {
|
||||
executor.notify(String.format("Usage: %s", getUsage(executor)), SYSTEM);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = GameServer.getInstance().getPlayerManager().getPlayer(args[0]);
|
||||
|
||||
if(player == null) {
|
||||
executor.notify("This player does not exist.", SYSTEM);
|
||||
return;
|
||||
} else if(!player.isOnline()) {
|
||||
executor.notify("This player is offline.", SYSTEM);
|
||||
return;
|
||||
} else if(!player.isV3()) {
|
||||
executor.notify("Cannot open URLs on iOS clients.", SYSTEM);
|
||||
return;
|
||||
}
|
||||
|
||||
player.sendMessage(new EventMessage("openUrl", "https://www.youtube.com/watch?v=dQw4w9WgXcQ"));
|
||||
executor.notify(String.format("Successfully rickrolled %s!", player.getName()), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "rickroll";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Makes a player hate you forever.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/rickroll <player>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(CommandExecutor executor) {
|
||||
return executor.isAdmin();
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
|
||||
public class StopCommand extends Command {
|
||||
|
||||
@Override
|
||||
public void execute(CommandExecutor executor, String[] args) {
|
||||
GameServer.getInstance().stopGracefully(); // YEET!!
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "stop";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "exit", "close", "shutdown" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Gracefully shuts down the server after the current tick.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(CommandExecutor executor) {
|
||||
return executor.isAdmin();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package brainwine.gameserver.commands;
|
||||
|
||||
public abstract class Command {
|
||||
|
||||
public abstract void execute(CommandExecutor executor, String[] args);
|
||||
public abstract String getUsage(CommandExecutor executor);
|
||||
|
||||
public boolean canExecute(CommandExecutor executor) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.command;
|
||||
package brainwine.gameserver.commands;
|
||||
|
||||
import brainwine.gameserver.entity.player.NotificationType;
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
package brainwine.gameserver.commands;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
import static brainwine.shared.LogMarkers.SERVER_MARKER;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class CommandManager {
|
||||
|
||||
public static final String CUSTOM_COMMAND_PREFIX = "!"; // TODO configurable
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
private static final Map<String, Command> commands = new HashMap<>();
|
||||
private static final Map<String, Command> aliases = new HashMap<>();
|
||||
private static boolean initialized = false;
|
||||
|
||||
public static void init() {
|
||||
if(initialized) {
|
||||
logger.warn(SERVER_MARKER, "CommandManager is already initialized - skipping!");
|
||||
return;
|
||||
}
|
||||
|
||||
registerCommands();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
private static void registerCommands() {
|
||||
logger.info(SERVER_MARKER, "Registering commands ...");
|
||||
Reflections reflections = new Reflections("brainwine.gameserver.commands");
|
||||
Set<Class<?>> classes = reflections.getTypesAnnotatedWith(CommandInfo.class);
|
||||
|
||||
for(Class<?> clazz : classes) {
|
||||
if(!Command.class.isAssignableFrom(clazz)) {
|
||||
logger.warn(SERVER_MARKER, "Attempted to register non-command class {}", clazz.getSimpleName());
|
||||
continue;
|
||||
}
|
||||
|
||||
registerCommand((Class<? extends Command>)clazz);
|
||||
}
|
||||
}
|
||||
|
||||
public static void executeCommand(CommandExecutor executor, String commandLine) {
|
||||
if(commandLine.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
commandLine.trim().replaceAll(" +", " ");
|
||||
String[] sections = commandLine.split(" ", 2);
|
||||
|
||||
if(sections.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String name = sections[0];
|
||||
String[] args = sections.length > 1 ? sections[1].split(" ") : new String[0];
|
||||
executeCommand(executor, name, args);
|
||||
}
|
||||
|
||||
public static void executeCommand(CommandExecutor executor, String commandName, String[] args) {
|
||||
if(!(executor instanceof Player) && commandName.startsWith(CUSTOM_COMMAND_PREFIX) || commandName.startsWith("/")) {
|
||||
commandName = commandName.substring(1);
|
||||
}
|
||||
|
||||
Command command = getCommand(commandName, true);
|
||||
|
||||
if(command == null || !command.canExecute(executor)) {
|
||||
executor.notify("Unknown command. Type '/help' for a list of commands.", SYSTEM);
|
||||
return;
|
||||
}
|
||||
|
||||
if(executor instanceof Player) {
|
||||
Player player = (Player)executor;
|
||||
logger.info(SERVER_MARKER, "{} used command '/{}'", player.getName(), commandName + (args.length == 0 ? "" : " " + String.join(" ", args)));
|
||||
}
|
||||
|
||||
command.execute(executor, args);
|
||||
}
|
||||
|
||||
public static void registerCommand(Class<? extends Command> type) {
|
||||
CommandInfo info = type.getAnnotation(CommandInfo.class);
|
||||
|
||||
if(info == null) {
|
||||
logger.warn(SERVER_MARKER, "Cannot register command '{}' because it does not have the CommandInfo annotation", type.getSimpleName());
|
||||
return;
|
||||
}
|
||||
|
||||
String name = info.name();
|
||||
String[] aliases = info.aliases();
|
||||
|
||||
if(commands.containsKey(name)) {
|
||||
logger.warn(SERVER_MARKER, "Attempted to register duplicate command '{}' with name '{}'", type.getSimpleName(), name);
|
||||
return;
|
||||
}
|
||||
|
||||
Command command = null;
|
||||
|
||||
try {
|
||||
command = type.getConstructor().newInstance();
|
||||
} catch(ReflectiveOperationException e) {
|
||||
logger.error("Failed to not instantiate command '{}'", type.getSimpleName(), e);
|
||||
return;
|
||||
}
|
||||
|
||||
commands.put(name, command);
|
||||
|
||||
if(aliases != null) {
|
||||
for(String alias : aliases) {
|
||||
if(commands.containsKey(alias) || CommandManager.aliases.containsKey(alias)) {
|
||||
logger.warn(SERVER_MARKER, "Duplicate alias {} for command {}", alias, command.getClass());
|
||||
continue;
|
||||
}
|
||||
|
||||
CommandManager.aliases.put(alias, command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getCommandNames() {
|
||||
Set<String> names = new HashSet<>();
|
||||
names.addAll(commands.keySet());
|
||||
names.addAll(aliases.keySet());
|
||||
return names;
|
||||
}
|
||||
|
||||
public static Command getCommand(String name) {
|
||||
return getCommand(name, false);
|
||||
}
|
||||
|
||||
public static Command getCommand(String name, boolean allowAlias) {
|
||||
return commands.getOrDefault(name, allowAlias ? aliases.get(name) : null);
|
||||
}
|
||||
|
||||
public static Collection<Command> getCommands() {
|
||||
return Collections.unmodifiableCollection(commands.values());
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
|
@ -8,16 +8,20 @@ import java.util.List;
|
|||
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.command.CommandManager;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
|
||||
@CommandInfo(name = "help", description = "Displays a list of commands.")
|
||||
public class HelpCommand extends Command {
|
||||
|
||||
@Override
|
||||
public void execute(CommandExecutor executor, String[] args) {
|
||||
List<Command> commands = new ArrayList<>(CommandManager.getCommands());
|
||||
commands.removeIf(command -> !command.canExecute(executor));
|
||||
commands.sort((a, b) -> {
|
||||
CommandInfo info1 = a.getClass().getAnnotation(CommandInfo.class);
|
||||
CommandInfo info2 = b.getClass().getAnnotation(CommandInfo.class);
|
||||
return info1.name().compareTo(info2.name());
|
||||
});
|
||||
int pageSize = 8;
|
||||
int pageCount = (int)Math.ceil(commands.size() / (double)pageSize);
|
||||
int page = 1;
|
||||
|
@ -41,11 +45,12 @@ public class HelpCommand extends Command {
|
|||
return;
|
||||
}
|
||||
|
||||
executor.notify(String.format("========== Information about '/%s' ==========", command.getName()), SYSTEM);
|
||||
executor.notify(String.format("Description: %s", command.getDescription()), SYSTEM);
|
||||
CommandInfo info = command.getClass().getAnnotation(CommandInfo.class);
|
||||
executor.notify(String.format("========== Information about '/%s' ==========", info.name()), SYSTEM);
|
||||
executor.notify(String.format("Description: %s", info.description()), SYSTEM);
|
||||
executor.notify(String.format("Usage: %s", command.getUsage(executor)), SYSTEM);
|
||||
executor.notify(String.format("Aliases: %s", command.getAliases() == null ? "None :("
|
||||
: Arrays.toString(command.getAliases())), SYSTEM);
|
||||
executor.notify(String.format("Aliases: %s", info.aliases() == null ? "None :("
|
||||
: Arrays.toString(info.aliases())), SYSTEM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -56,19 +61,10 @@ public class HelpCommand extends Command {
|
|||
executor.notify(String.format("========== Command List (Page %s of %s) ==========", page, pageCount), SYSTEM);
|
||||
|
||||
for(Command command : commandsToDisplay) {
|
||||
executor.notify(String.format("%s - %s", command.getUsage(executor), command.getDescription()), SYSTEM);
|
||||
CommandInfo info = command.getClass().getAnnotation(CommandInfo.class);
|
||||
executor.notify(String.format("%s - %s", command.getUsage(executor), info.description()), SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "help";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays command information.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,16 +1,16 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands;
|
||||
|
||||
import org.apache.commons.validator.routines.EmailValidator;
|
||||
import org.mindrot.jbcrypt.BCrypt;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.dialog.DialogHelper;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
@CommandInfo(name = "register", description = "Shows a prompt with which you can register your account.")
|
||||
public class RegisterCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -55,13 +55,8 @@ public class RegisterCommand extends Command {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "register";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Shows a prompt with which you can register your account.";
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/register";
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,12 +1,12 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.entity.player.ChatType;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "say", description = "Shows a speech bubble to nearby players.")
|
||||
public class SayCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -27,16 +27,6 @@ public class SayCommand extends Command {
|
|||
player.getZone().sendChatMessage(player, text, ChatType.SPEECH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "say";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Shows a speech bubble to nearby players.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/say <message>";
|
|
@ -1,12 +1,12 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.entity.player.ChatType;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "think", description = "Shows a thought bubble to nearby players.")
|
||||
public class ThinkCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -27,16 +27,6 @@ public class ThinkCommand extends Command {
|
|||
player.getZone().sendChatMessage(player, text, ChatType.THOUGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "think";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Shows a thought bubble to nearby players.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/think <message>";
|
|
@ -1,12 +1,14 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
|
||||
@CommandInfo(name = "acidity", description = "Displays or changes the acidity in the current zone.")
|
||||
public class AcidityCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -35,16 +37,6 @@ public class AcidityCommand extends Command {
|
|||
zone.setAcidity(value);
|
||||
executor.notify(String.format("Acidity has been set to %s in %s.", value, zone.getName()), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "acidity";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays or changes the acidity in the current zone.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,12 +1,14 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "admin", description = "Grants or revokes administrator rights.")
|
||||
public class AdminCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -38,16 +40,6 @@ public class AdminCommand extends Command {
|
|||
executor.notify(String.format("Changed administrator status of player %s to %s", target.getName(), admin), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "admin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Allows you to grant or revoke administrator rights.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/admin <player> [true|false]";
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
|
@ -7,11 +7,13 @@ import java.time.format.DateTimeFormatter;
|
|||
import java.util.Arrays;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.util.DateTimeUtils;
|
||||
|
||||
@CommandInfo(name = "ban", description = "Bans a player from the server.")
|
||||
public class BanCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -58,21 +60,6 @@ public class BanCommand extends Command {
|
|||
target.getName(), endDate.format(DateTimeFormatter.RFC_1123_DATE_TIME), reason), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "ban";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "banish" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Bans a player from the server.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/ban <player> <duration> [reason]";
|
|
@ -1,13 +1,15 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.POPUP;
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "broadcast", description = "Broadcasts a message to all online players.", aliases = "bc")
|
||||
public class BroadcastCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -26,21 +28,6 @@ public class BroadcastCommand extends Command {
|
|||
executor.notify("Your message has been broadcasted.", POPUP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "broadcast";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "bc" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Broadcasts a message to all online players.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/broadcast <message>";
|
|
@ -0,0 +1,39 @@
|
|||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.NotificationType;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "entity", description = "Spawns an entity at your current location.")
|
||||
public class EntityCommand extends Command {
|
||||
|
||||
@Override
|
||||
public void execute(CommandExecutor executor, String[] args) {
|
||||
if(args.length == 0) {
|
||||
executor.notify(String.format("Usage: %s", getUsage(executor)), SYSTEM);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player)executor;
|
||||
String type = args[0];
|
||||
|
||||
if(player.getZone().spawnEntity(type, player.getBlockX(), player.getBlockY(), true) == null) {
|
||||
executor.notify(String.format("Entity type '%s' does not exist.", type), NotificationType.SYSTEM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/entity <type>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(CommandExecutor executor) {
|
||||
return executor.isAdmin() && executor instanceof Player;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "experience", description = "Sets the experience of the target player.", aliases = { "xp", "exp" })
|
||||
public class ExperienceCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -53,21 +55,6 @@ public class ExperienceCommand extends Command {
|
|||
target.setExperience(experience);
|
||||
executor.notify(String.format("Successfully set %s's experience to %s.", target.getName(), experience), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "experience";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "xp", "exp" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Sets the experience of the target player.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
|
@ -6,13 +6,15 @@ import java.util.Arrays;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.prefab.Prefab;
|
||||
import brainwine.gameserver.prefab.PrefabManager;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
|
||||
@CommandInfo(name = "export", description = "Exports a section of a zone to a prefab file.")
|
||||
public class ExportCommand extends Command {
|
||||
|
||||
public static final Pattern PREFAB_NAME_PATTERN = Pattern.compile("\\w+(/\\w+)*");
|
||||
|
@ -80,16 +82,6 @@ public class ExportCommand extends Command {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "export";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Exports a section of a zone to a prefab file.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/export <x> <y> <width> <height> <name>";
|
|
@ -1,14 +1,16 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.zone.Biome;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
import brainwine.gameserver.zone.gen.ZoneGenerator;
|
||||
|
||||
@CommandInfo(name = "genzone", description = "Asynchronously generates a new zone.", aliases = "generate")
|
||||
public class GenerateZoneCommand extends Command {
|
||||
|
||||
public static final int MIN_WIDTH = 200;
|
||||
|
@ -18,20 +20,20 @@ public class GenerateZoneCommand extends Command {
|
|||
|
||||
@Override
|
||||
public void execute(CommandExecutor executor, String[] args) {
|
||||
Biome biome = Biome.getRandomBiome();
|
||||
int width = 2000;
|
||||
int height = 600;
|
||||
Biome biome = args.length > 0 ? Biome.fromName(args[0]) : Biome.getRandomBiome();
|
||||
int width = biome == Biome.DEEP ? 1200 : 2000;
|
||||
int height = biome == Biome.DEEP ? 1000 : 600;
|
||||
int seed = (int)(Math.random() * Integer.MAX_VALUE);
|
||||
|
||||
if(args.length > 0 && args.length < 2) {
|
||||
if(args.length > 1 && args.length < 3) {
|
||||
executor.notify(String.format("Usage: %s", getUsage(executor)), SYSTEM);
|
||||
return;
|
||||
}
|
||||
|
||||
if(args.length >= 2) {
|
||||
if(args.length >= 3) {
|
||||
try {
|
||||
width = Integer.parseInt(args[0]);
|
||||
height = Integer.parseInt(args[1]);
|
||||
width = Integer.parseInt(args[1]);
|
||||
height = Integer.parseInt(args[2]);
|
||||
} catch(NumberFormatException e) {
|
||||
executor.notify("Zone width and height must be valid numbers.", SYSTEM);
|
||||
return;
|
||||
|
@ -47,10 +49,6 @@ public class GenerateZoneCommand extends Command {
|
|||
}
|
||||
}
|
||||
|
||||
if(args.length >= 3) {
|
||||
biome = Biome.fromName(args[2]);
|
||||
}
|
||||
|
||||
ZoneGenerator generator = null;
|
||||
|
||||
if(args.length >= 4) {
|
||||
|
@ -88,25 +86,10 @@ public class GenerateZoneCommand extends Command {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "genzone";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "generate" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Asynchronously generates a new zone.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/genzone [<width> <height>] [biome] [generator] [seed]";
|
||||
return "/genzone [biome] [<width> <height>] [generator] [seed]";
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
|
@ -6,12 +6,14 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.ItemRegistry;
|
||||
|
||||
@CommandInfo(name = "give", description = "Give or take items from players.")
|
||||
public class GiveCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -35,7 +37,7 @@ public class GiveCommand extends Command {
|
|||
title = "of every item";
|
||||
|
||||
for(Item item : ItemRegistry.getItems()) {
|
||||
if(!item.isClothing() && !item.isAir()) {
|
||||
if(!item.isAir()) {
|
||||
items.add(item);
|
||||
}
|
||||
}
|
||||
|
@ -84,16 +86,6 @@ public class GiveCommand extends Command {
|
|||
executor.notify(String.format("Took %s %s from %s", -quantity, title, target.getName()), SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "give";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Adds items to a player's inventory.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,12 +1,14 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "health", description = "Sets the target player's health.", aliases = "hp")
|
||||
public class HealthCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -47,21 +49,6 @@ public class HealthCommand extends Command {
|
|||
executor.notify(String.format("Set %s's health to %s", target.getName(), target.getHealth()), SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "health";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "hp" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Sets a player's health.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,13 +1,15 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.prefab.Prefab;
|
||||
|
||||
@CommandInfo(name = "import", description = "Places a prefab at the specified location.")
|
||||
public class ImportCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -46,16 +48,6 @@ public class ImportCommand extends Command {
|
|||
player.notify(String.format("Successfully imported '%s' @ [x: %s, y: %s, width: %s, height: %s]",
|
||||
name, x, y, prefab.getWidth(), prefab.getHeight()), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "import";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Places a prefab at your or a specified location.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,14 +1,16 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "kick", description = "Kicks a player from the server.")
|
||||
public class KickCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -38,16 +40,6 @@ public class KickCommand extends Command {
|
|||
executor.notify("Kicked player " + player.getName() + " for '" + reason + "'", SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "kick";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Kicks a player from the server.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/kick <player> [reason]";
|
|
@ -1,12 +1,14 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "level", description = "Sets the level of the target player.", aliases = { "lvl", "lv" })
|
||||
public class LevelCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -55,21 +57,6 @@ public class LevelCommand extends Command {
|
|||
target.setLevel(level);
|
||||
executor.notify(String.format("Successfully set %s's level to %s.", target.getName(), level), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "level";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "lvl", "lv" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Sets the level of the target player.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
|
@ -7,11 +7,13 @@ import java.time.format.DateTimeFormatter;
|
|||
import java.util.Arrays;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.util.DateTimeUtils;
|
||||
|
||||
@CommandInfo(name = "mute", description = "Mutes a player, preventing them from chatting.", aliases = "silence")
|
||||
public class MuteCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -58,21 +60,6 @@ public class MuteCommand extends Command {
|
|||
target.getName(), endDate.format(DateTimeFormatter.RFC_1123_DATE_TIME), reason), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "mute";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "silence", };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Mutes a player, preventing them from chatting.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/mute <player> <duration> [reason]";
|
|
@ -1,12 +1,14 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "pid", description = "Displays the document id of a player.")
|
||||
public class PlayerIdCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -34,16 +36,6 @@ public class PlayerIdCommand extends Command {
|
|||
executor.notify(target.getDocumentId(), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "pid";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays the document id of a player.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return String.format("/pid %s", executor instanceof Player ? "[player]" : "<player>");
|
|
@ -1,11 +1,13 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "position", description = "Displays the coordinates of the block you are standing on.", aliases = { "pos", "feet", "coords", "location" })
|
||||
public class PositionCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -13,21 +15,6 @@ public class PositionCommand extends Command {
|
|||
Player player = (Player)executor;
|
||||
player.notify(String.format("X: %s Y: %s", (int)player.getX(), (int)player.getY() + 1), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "pos";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "position", "feet", "coords", "location" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays the coordinates of the block you are standing on.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
|
@ -8,10 +8,12 @@ import java.util.List;
|
|||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.prefab.Prefab;
|
||||
|
||||
@CommandInfo(name = "prefabs", description = "Displays a list of all prefabs.")
|
||||
public class PrefabListCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -34,21 +36,6 @@ public class PrefabListCommand extends Command {
|
|||
executor.notify(prefab.getName(), SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "prefabs";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "prefablist" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays a list of all prefabs.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,13 +1,15 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
|
||||
@CommandInfo(name = "seed", description = "Displays the seed of a zone.")
|
||||
public class SeedCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -35,16 +37,6 @@ public class SeedCommand extends Command {
|
|||
executor.notify("Seed: " + target.getSeed(), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "seed";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays the seed of a zone.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return String.format("/seed %s", executor instanceof Player ? "[zone]" : "<zone>");
|
|
@ -1,11 +1,13 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "settle", description = "Settles all liquids in all active chunks in the current zone. Warning - can cause lag!")
|
||||
public class SettleLiquidsCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -19,18 +21,8 @@ public class SettleLiquidsCommand extends Command {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "settleliquids";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] {"settle"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Settles all liquids in all active chunks in the current zone. Warning - can cause lag!";
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/settle";
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,12 +1,14 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "skillpoints", description = "Sets the skill points of the target player.", aliases = "points")
|
||||
public class SkillPointsCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -54,21 +56,6 @@ public class SkillPointsCommand extends Command {
|
|||
target.notify(String.format("Your skill point count has been set to %s.", amount), SYSTEM);
|
||||
executor.notify(String.format("Successfully set %s's skill point count to %s.", target.getName(), amount), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "skillpoints";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "points" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Sets the skill points of the target player.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -0,0 +1,25 @@
|
|||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
|
||||
@CommandInfo(name = "stop", description = "Gracefully shuts down the server.", aliases = { "exit", "close", "shutdown" })
|
||||
public class StopCommand extends Command {
|
||||
|
||||
@Override
|
||||
public void execute(CommandExecutor executor, String[] args) {
|
||||
GameServer.getInstance().stopGracefully(); // YEET!!
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/stop";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(CommandExecutor executor) {
|
||||
return executor.isAdmin();
|
||||
}
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "teleport", description = "Teleports you to the specified position.", aliases = "tp")
|
||||
public class TeleportCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -35,21 +37,6 @@ public class TeleportCommand extends Command {
|
|||
player.teleport(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "teleport";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "tp" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Teleports you to the specified position.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/teleport <x> <y>";
|
|
@ -1,12 +1,14 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
|
||||
@CommandInfo(name = "time", description = "Displays or changes the time in the current zone.")
|
||||
public class TimeCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -45,16 +47,6 @@ public class TimeCommand extends Command {
|
|||
zone.setTime(value);
|
||||
executor.notify(String.format("Time has been set to %s in %s.", value, zone.getName()), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "time";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays or changes the time in the current zone.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,12 +1,14 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "unban", description = "Unbans a player.", aliases = "pardon")
|
||||
public class UnbanCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -31,21 +33,6 @@ public class UnbanCommand extends Command {
|
|||
target.unban(executor instanceof Player ? (Player)executor : null);
|
||||
executor.notify(String.format("Player %s has been unbanned.", target.getName()), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "unban";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[] { "pardon" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Unbans a player.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,12 +1,14 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
@CommandInfo(name = "unmute", description = "Unmutes a player.")
|
||||
public class UnmuteCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -31,16 +33,6 @@ public class UnmuteCommand extends Command {
|
|||
target.unmute(executor instanceof Player ? (Player)executor : null);
|
||||
executor.notify(String.format("Player %s has been unmuted.", target.getName()), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "unmute";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Unmutes a player.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,14 +1,16 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.zone.Biome;
|
||||
import brainwine.gameserver.zone.WeatherManager;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
|
||||
@CommandInfo(name = "weather", description = "Displays or changes the weather in the current zone.")
|
||||
public class WeatherCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -32,16 +34,6 @@ public class WeatherCommand extends Command {
|
|||
zone.getWeatherManager().createRandomRain(dry);
|
||||
executor.notify(String.format("Weather has been %s in %s.", dry ? "cleared" : "made rainy", zone.getName()), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "weather";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays or changes the weather in the current zone.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
|
@ -1,13 +1,15 @@
|
|||
package brainwine.gameserver.command.commands;
|
||||
package brainwine.gameserver.commands.admin;
|
||||
|
||||
import static brainwine.gameserver.entity.player.NotificationType.SYSTEM;
|
||||
|
||||
import brainwine.gameserver.GameServer;
|
||||
import brainwine.gameserver.command.Command;
|
||||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.annotations.CommandInfo;
|
||||
import brainwine.gameserver.commands.Command;
|
||||
import brainwine.gameserver.commands.CommandExecutor;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
|
||||
@CommandInfo(name = "zid", description = "Displays the document id of a zone.")
|
||||
public class ZoneIdCommand extends Command {
|
||||
|
||||
@Override
|
||||
|
@ -35,16 +37,6 @@ public class ZoneIdCommand extends Command {
|
|||
executor.notify(target.getDocumentId(), SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "zid";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays the document id of a zone.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return String.format("/zid %s", executor instanceof Player ? "[zone]" : "<zone>");
|
|
@ -1,12 +1,15 @@
|
|||
package brainwine.gameserver.dialog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
|
||||
@JsonInclude(Include.NON_DEFAULT)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
|
@ -15,6 +18,7 @@ public class Dialog {
|
|||
private DialogType type = DialogType.STANDARD;
|
||||
private DialogAlignment alignment = DialogAlignment.LEFT;
|
||||
private List<DialogSection> sections = new ArrayList<>();
|
||||
private Object actions;
|
||||
private String title;
|
||||
private String target;
|
||||
|
||||
|
@ -61,6 +65,29 @@ public class Dialog {
|
|||
return sections;
|
||||
}
|
||||
|
||||
@JsonSetter
|
||||
private void setActions(Object actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
public Dialog setActions(String actions) {
|
||||
this.actions = actions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Dialog setActions(String... actions) {
|
||||
return setActions(Arrays.asList(actions));
|
||||
}
|
||||
|
||||
public Dialog setActions(Collection<String> actions) {
|
||||
this.actions = actions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public Dialog setTitle(String title) {
|
||||
this.title = title;
|
||||
return this;
|
||||
|
|
|
@ -3,13 +3,15 @@ package brainwine.gameserver.dialog;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
|
||||
|
||||
import brainwine.gameserver.dialog.input.DialogInput;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import brainwine.gameserver.util.Vector2i;
|
||||
|
||||
@JsonInclude(Include.NON_DEFAULT)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
|
@ -20,6 +22,7 @@ public class DialogSection {
|
|||
private String text;
|
||||
private String textColor;
|
||||
private double textScale;
|
||||
private Vector2i location;
|
||||
private DialogInput input;
|
||||
|
||||
public DialogSection addItem(DialogListItem item) {
|
||||
|
@ -75,6 +78,20 @@ public class DialogSection {
|
|||
return textScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* v2 clients only!
|
||||
*/
|
||||
public DialogSection setLocation(int x, int y) {
|
||||
this.location = new Vector2i(x, y);
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("map")
|
||||
@JsonFormat(shape = Shape.ARRAY)
|
||||
public Vector2i getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public DialogSection setInput(DialogInput input) {
|
||||
this.input = input;
|
||||
return this;
|
||||
|
|
|
@ -3,9 +3,12 @@ package brainwine.gameserver.dialog.input;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class DialogSelectInput extends DialogInput {
|
||||
|
||||
private Collection<String> options;
|
||||
private int maxColumns;
|
||||
|
||||
public DialogSelectInput setOptions(String... options) {
|
||||
return setOptions(Arrays.asList(options));
|
||||
|
@ -19,4 +22,14 @@ public class DialogSelectInput extends DialogInput {
|
|||
public Collection<String> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public DialogSelectInput setMaxColumns(int maxColumns) {
|
||||
this.maxColumns = maxColumns;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("max columns")
|
||||
public int getMaxColumns() {
|
||||
return maxColumns;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
package brainwine.gameserver.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.item.DamageType;
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.ItemUseType;
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.server.Message;
|
||||
import brainwine.gameserver.server.messages.EffectMessage;
|
||||
import brainwine.gameserver.server.messages.EntityChangeMessage;
|
||||
import brainwine.gameserver.server.messages.EntityStatusMessage;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
import brainwine.gameserver.util.MathUtils;
|
||||
import brainwine.gameserver.zone.Block;
|
||||
import brainwine.gameserver.zone.MetaBlock;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
|
||||
public abstract class Entity {
|
||||
|
@ -18,8 +26,11 @@ public abstract class Entity {
|
|||
public static final float DEFAULT_HEALTH = 5;
|
||||
public static final float POSITION_MODIFIER = 100F;
|
||||
public static final int VELOCITY_MODIFIER = (int)POSITION_MODIFIER;
|
||||
public static final int ATTACK_RETENTION_TIME = 2000;
|
||||
public static final int ATTACK_INVINCIBLE_TIME = 333;
|
||||
protected final Map<String, Object> properties = new HashMap<>();
|
||||
protected final List<Player> trackers = new ArrayList<>();
|
||||
protected final List<EntityAttack> recentAttacks = new ArrayList<>();
|
||||
protected int type;
|
||||
protected String name;
|
||||
protected float health = DEFAULT_HEALTH;
|
||||
|
@ -29,10 +40,18 @@ public abstract class Entity {
|
|||
protected float y;
|
||||
protected float velocityX;
|
||||
protected float velocityY;
|
||||
protected int blockX;
|
||||
protected int blockY;
|
||||
protected int lastBlockX;
|
||||
protected int lastBlockY;
|
||||
protected int targetX;
|
||||
protected int targetY;
|
||||
protected int sizeX = 1;
|
||||
protected int sizeY = 1;
|
||||
protected FacingDirection direction = FacingDirection.WEST;
|
||||
protected int animation;
|
||||
protected boolean invulnerable;
|
||||
protected EntityAttack lastAttack; // Used for tracking in entity deaths -- do not use this for anything else!
|
||||
protected long lastDamagedAt;
|
||||
|
||||
public Entity(Zone zone) {
|
||||
|
@ -40,10 +59,16 @@ public abstract class Entity {
|
|||
}
|
||||
|
||||
public void tick(float deltaTime) {
|
||||
// Override
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
// Update block position
|
||||
updateBlockPosition();
|
||||
|
||||
// Clear expired recent attacks
|
||||
recentAttacks.removeIf(attack -> now >= attack.getTime() + ATTACK_RETENTION_TIME);
|
||||
}
|
||||
|
||||
public void die(Player killer) {
|
||||
public void die(EntityAttack cause) {
|
||||
// Override
|
||||
}
|
||||
|
||||
|
@ -53,18 +78,93 @@ public abstract class Entity {
|
|||
}
|
||||
}
|
||||
|
||||
public void damage(float amount) {
|
||||
damage(amount, null);
|
||||
public void attack(Entity attacker, Item weapon, float baseDamage, DamageType damageType) {
|
||||
attack(attacker, weapon, baseDamage, damageType, false);
|
||||
}
|
||||
|
||||
public void damage(float amount, Player attacker) {
|
||||
setHealth(health - amount);
|
||||
|
||||
if(health <= 0) {
|
||||
die(attacker);
|
||||
public void attack(Entity attacker, Item weapon, float baseDamage, DamageType damageType, boolean trueDamage) {
|
||||
// Ignore attack if entity is dead or invulnerable
|
||||
if(isDead() || isInvulnerable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore attack if there is no damage to deal
|
||||
if(baseDamage <= 0 || damageType == null || damageType == DamageType.NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityAttack attack = new EntityAttack(attacker, weapon, baseDamage, damageType);
|
||||
recentAttacks.add(attack);
|
||||
lastAttack = attack;
|
||||
lastDamagedAt = System.currentTimeMillis();
|
||||
|
||||
// Kill entity if attacker is a player in god mode
|
||||
if(attacker != null && attacker.isPlayer() && ((Player)attacker).isGodMode()) {
|
||||
setHealth(0.0F);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore multipliers if true damage should be dealt
|
||||
if(trueDamage) {
|
||||
setHealth(health - baseDamage);
|
||||
return;
|
||||
}
|
||||
|
||||
float attackMultiplier = attacker != null ? Math.max(0.0F, attacker.getAttackMultiplier(attack)) : 1.0F;
|
||||
float defense = Math.max(0.0F, 1.0F - getDefense(attack));
|
||||
float damage = baseDamage * attackMultiplier * defense;
|
||||
setHealth(health - damage);
|
||||
}
|
||||
|
||||
public float getAttackMultiplier(EntityAttack attack) {
|
||||
return 1.0F; // Override
|
||||
}
|
||||
|
||||
public float getDefense(EntityAttack attack) {
|
||||
return 1.0F; // Override
|
||||
}
|
||||
|
||||
public void spawnEffect(String type) {
|
||||
spawnEffect(type, 1);
|
||||
}
|
||||
|
||||
public void spawnEffect(String type, Object data) {
|
||||
float effectX = x + sizeX / 2.0F;
|
||||
float effectY = y + sizeY / 2.0F;
|
||||
sendMessageToTrackers(new EffectMessage(effectX, effectY, type, data));
|
||||
}
|
||||
|
||||
public void emote(String message) {
|
||||
float effectX = x + sizeX / 2.0F;
|
||||
float effectY = y - sizeY + 1;
|
||||
sendMessageToTrackers(new EffectMessage(effectX, effectY, "emote", message));
|
||||
}
|
||||
|
||||
public void updateBlockPosition() {
|
||||
lastBlockX = blockX;
|
||||
lastBlockY = blockY;
|
||||
blockX = (int)x;
|
||||
blockY = (int)y;
|
||||
|
||||
// Check if block position has changed
|
||||
if(lastBlockX != blockX || lastBlockY != blockY) {
|
||||
blockPositionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void blockPositionChanged() {
|
||||
// Check for touchplates
|
||||
if(zone != null && zone.isChunkLoaded(blockX, blockY)) {
|
||||
MetaBlock metaBlock = zone.getMetaBlock(blockX, blockY);
|
||||
Block block = zone.getBlock(blockX, blockY);
|
||||
Item item = block.getFrontItem();
|
||||
int mod = block.getFrontMod();
|
||||
|
||||
// Trigger a switch interaction if the entity stepped on a touchplate
|
||||
if(item.hasUse(ItemUseType.TRIGGER)) {
|
||||
ItemUseType.SWITCH.getInteraction().interact(zone, this, blockX, blockY, Layer.FRONT, item, mod, metaBlock, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canSee(Entity other) {
|
||||
|
@ -80,7 +180,7 @@ public abstract class Entity {
|
|||
return inRange(other.getX(), other.getY(), range);
|
||||
}
|
||||
|
||||
public boolean inRange(float x, float y, float range) {
|
||||
public boolean inRange(float x, float y, double range) {
|
||||
return MathUtils.inRange(this.x, this.y, x, y, range);
|
||||
}
|
||||
|
||||
|
@ -128,6 +228,18 @@ public abstract class Entity {
|
|||
return trackers;
|
||||
}
|
||||
|
||||
public boolean wasAttackedRecently(Entity entity, int delay) {
|
||||
return recentAttacks.stream().filter(attack -> attack.getAttacker() == entity && System.currentTimeMillis() < attack.getTime() + delay).findFirst().isPresent();
|
||||
}
|
||||
|
||||
public EntityAttack getMostRecentAttack() {
|
||||
return recentAttacks.isEmpty() ? null : recentAttacks.get(recentAttacks.size() - 1);
|
||||
}
|
||||
|
||||
public List<EntityAttack> getRecentAttacks() {
|
||||
return Collections.unmodifiableList(recentAttacks);
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
@ -159,6 +271,12 @@ public abstract class Entity {
|
|||
public void setHealth(float health) {
|
||||
float maxHealth = getMaxHealth();
|
||||
this.health = health < 0 ? 0 : health > maxHealth ? maxHealth : health;
|
||||
|
||||
if(this.health <= 0.0F) {
|
||||
die(lastAttack);
|
||||
}
|
||||
|
||||
lastAttack = null;
|
||||
}
|
||||
|
||||
public float getHealth() {
|
||||
|
@ -168,6 +286,7 @@ public abstract class Entity {
|
|||
public void setPosition(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
updateBlockPosition();
|
||||
}
|
||||
|
||||
public float getX() {
|
||||
|
@ -204,6 +323,22 @@ public abstract class Entity {
|
|||
return targetY;
|
||||
}
|
||||
|
||||
public int getBlockX() {
|
||||
return blockX;
|
||||
}
|
||||
|
||||
public int getBlockY() {
|
||||
return blockY;
|
||||
}
|
||||
|
||||
public int getSizeX() {
|
||||
return sizeX;
|
||||
}
|
||||
|
||||
public int getSizeY() {
|
||||
return sizeY;
|
||||
}
|
||||
|
||||
public void setDirection(FacingDirection direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
@ -220,6 +355,14 @@ public abstract class Entity {
|
|||
return animation;
|
||||
}
|
||||
|
||||
public void setInvulnerable(boolean invulnerable) {
|
||||
this.invulnerable = invulnerable;
|
||||
}
|
||||
|
||||
public boolean isInvulnerable() {
|
||||
return invulnerable;
|
||||
}
|
||||
|
||||
public void setZone(Zone zone) {
|
||||
this.zone = zone;
|
||||
}
|
||||
|
@ -228,6 +371,10 @@ public abstract class Entity {
|
|||
return zone;
|
||||
}
|
||||
|
||||
public final boolean isPlayer() {
|
||||
return this instanceof Player; // Not very OOP
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A {@link Map} containing all the data necessary for use in {@link EntityStatusMessage}.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package brainwine.gameserver.entity;
|
||||
|
||||
import brainwine.gameserver.item.DamageType;
|
||||
import brainwine.gameserver.item.Item;
|
||||
|
||||
public class EntityAttack {
|
||||
|
||||
private final Entity attacker;
|
||||
private final Item weapon;
|
||||
private final float baseDamage;
|
||||
private final DamageType damageType;
|
||||
private final long time;
|
||||
|
||||
public EntityAttack(Entity attacker, Item weapon, float baseDamage, DamageType damageType) {
|
||||
this.attacker = attacker;
|
||||
this.weapon = weapon;
|
||||
this.baseDamage = baseDamage;
|
||||
this.damageType = damageType;
|
||||
this.time = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public Entity getAttacker() {
|
||||
return attacker;
|
||||
}
|
||||
|
||||
public Item getWeapon() {
|
||||
return weapon;
|
||||
}
|
||||
|
||||
public float getBaseDamage() {
|
||||
return baseDamage;
|
||||
}
|
||||
|
||||
public DamageType getDamageType() {
|
||||
return damageType;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
|
@ -29,6 +29,11 @@ public class EntityConfig {
|
|||
private int experienceYield;
|
||||
private float maxHealth = Entity.DEFAULT_HEALTH;
|
||||
private float baseSpeed = 3;
|
||||
private boolean character;
|
||||
private boolean human;
|
||||
private boolean named;
|
||||
private boolean trappable;
|
||||
private Item trappablePetItem;
|
||||
private Vector2i size = new Vector2i(1, 1);
|
||||
private EntityGroup group = EntityGroup.NONE;
|
||||
private WeightedMap<EntityLoot> loot = new WeightedMap<>();
|
||||
|
@ -79,6 +84,30 @@ public class EntityConfig {
|
|||
return baseSpeed;
|
||||
}
|
||||
|
||||
public boolean isCharacter() {
|
||||
return character;
|
||||
}
|
||||
|
||||
public boolean isHuman() {
|
||||
return human;
|
||||
}
|
||||
|
||||
public boolean isNamed() {
|
||||
return named;
|
||||
}
|
||||
|
||||
public boolean isTrappable() {
|
||||
return trappable;
|
||||
}
|
||||
|
||||
public boolean hasTrappablePetItem() {
|
||||
return trappablePetItem != null && !trappablePetItem.isAir();
|
||||
}
|
||||
|
||||
public Item getTrappablePetItem() {
|
||||
return trappablePetItem;
|
||||
}
|
||||
|
||||
@JsonSetter(nulls = Nulls.SKIP)
|
||||
private void setSize(Vector2i size) {
|
||||
this.size = size;
|
||||
|
|
|
@ -9,18 +9,20 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import brainwine.gameserver.behavior.SequenceBehavior;
|
||||
import brainwine.gameserver.Naming;
|
||||
import brainwine.gameserver.entity.Entity;
|
||||
import brainwine.gameserver.entity.EntityAttack;
|
||||
import brainwine.gameserver.entity.EntityConfig;
|
||||
import brainwine.gameserver.entity.EntityLoot;
|
||||
import brainwine.gameserver.entity.EntityRegistry;
|
||||
import brainwine.gameserver.entity.FacingDirection;
|
||||
import brainwine.gameserver.entity.npc.behavior.SequenceBehavior;
|
||||
import brainwine.gameserver.entity.player.Appearance;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
import brainwine.gameserver.item.DamageType;
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
import brainwine.gameserver.util.Pair;
|
||||
import brainwine.gameserver.util.Vector2i;
|
||||
import brainwine.gameserver.util.WeightedMap;
|
||||
import brainwine.gameserver.zone.MetaBlock;
|
||||
|
@ -28,13 +30,11 @@ import brainwine.gameserver.zone.Zone;
|
|||
|
||||
public class Npc extends Entity {
|
||||
|
||||
public static final int ATTACK_RETENTION_TIME = 2000;
|
||||
public static final int ATTACK_INVINCIBLE_TIME = 333;
|
||||
private final EntityConfig config;
|
||||
private final String typeName;
|
||||
private final float maxHealth;
|
||||
private final float baseSpeed;
|
||||
private final Vector2i size;
|
||||
private final boolean persist;
|
||||
private final WeightedMap<EntityLoot> loot;
|
||||
private final WeightedMap<EntityLoot> placedLoot;
|
||||
private final Map<Item, WeightedMap<EntityLoot>> lootByWeapon;
|
||||
|
@ -43,7 +43,6 @@ public class Npc extends Entity {
|
|||
private final List<String> animations;
|
||||
private final SequenceBehavior behaviorTree;
|
||||
private final Map<DamageType, Float> activeDefenses = new HashMap<>();
|
||||
private final Map<Player, Pair<Item, Long>> recentAttacks = new HashMap<>();
|
||||
private final List<Npc> children = new ArrayList<>();
|
||||
private float speed;
|
||||
private int moveX;
|
||||
|
@ -52,6 +51,7 @@ public class Npc extends Entity {
|
|||
private Vector2i mountBlock;
|
||||
private Entity owner;
|
||||
private Entity target;
|
||||
private boolean artificial;
|
||||
private long lastBehavedAt = System.currentTimeMillis();
|
||||
private long lastTrackedAt = System.currentTimeMillis();
|
||||
|
||||
|
@ -100,12 +100,24 @@ public class Npc extends Entity {
|
|||
properties.put("sl", slots);
|
||||
}
|
||||
|
||||
// Generate random name
|
||||
if(config.isNamed()) {
|
||||
this.name = Naming.getRandomEntityName();
|
||||
}
|
||||
|
||||
// Generate random appearance
|
||||
if(config.isHuman()) {
|
||||
properties.putAll(Appearance.getRandomAppearance());
|
||||
}
|
||||
|
||||
this.config = config;
|
||||
this.typeName = config.getName();
|
||||
this.type = config.getType();
|
||||
this.maxHealth = config.getMaxHealth();
|
||||
this.baseSpeed = config.getBaseSpeed();
|
||||
this.size = config.getSize();
|
||||
this.persist = config.isCharacter();
|
||||
this.sizeX = config.getSize().getX();
|
||||
this.sizeY = config.getSize().getY();
|
||||
this.loot = config.getLoot();
|
||||
this.placedLoot = config.getPlacedLoot();
|
||||
this.lootByWeapon = config.getLootByWeapon();
|
||||
|
@ -120,11 +132,9 @@ public class Npc extends Entity {
|
|||
|
||||
@Override
|
||||
public void tick(float deltaTime) {
|
||||
super.tick(deltaTime);
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
// Clear expired recent attacks
|
||||
recentAttacks.values().removeIf(attack -> now >= attack.getLast() + ATTACK_RETENTION_TIME);
|
||||
|
||||
// Tick behavior when it is ready
|
||||
if(now >= lastBehavedAt + (int)(1000 / speed)) {
|
||||
lastBehavedAt = now;
|
||||
|
@ -146,37 +156,17 @@ public class Npc extends Entity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void die(Player killer) {
|
||||
// Grant loot & track kill
|
||||
if(killer != null) {
|
||||
if(!isPlayerPlaced()) {
|
||||
// Track assists
|
||||
for(Player attacker : recentAttacks.keySet()) {
|
||||
if(attacker != killer) {
|
||||
attacker.getStatistics().trackAssist(config);
|
||||
}
|
||||
}
|
||||
|
||||
killer.getStatistics().trackKill(config);
|
||||
}
|
||||
|
||||
EntityLoot loot = getRandomLoot(killer);
|
||||
|
||||
if(loot != null) {
|
||||
Item item = loot.getItem();
|
||||
|
||||
if(!item.isAir()) {
|
||||
killer.getInventory().addItem(item, loot.getQuantity(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void die(EntityAttack cause) {
|
||||
// Remove itself from the guard block metadata if it was guarding one
|
||||
if(isGuard()) {
|
||||
MetaBlock metaBlock = zone.getMetaBlock(guardBlock.getX(), guardBlock.getY());
|
||||
|
||||
if(metaBlock != null) {
|
||||
MapHelper.getList(metaBlock.getMetadata(), "!", Collections.emptyList()).remove(typeName);
|
||||
List<String> guards = MapHelper.getList(metaBlock.getMetadata(), "!");
|
||||
|
||||
if(guards != null) {
|
||||
guards.remove(typeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,6 +174,41 @@ public class Npc extends Entity {
|
|||
if(isMounted()) {
|
||||
zone.updateBlock(mountBlock.getX(), mountBlock.getY(), Layer.FRONT, 0);
|
||||
}
|
||||
|
||||
// Do nothing else if cause data isn't present
|
||||
if(cause == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Entity killer = cause.getAttacker();
|
||||
|
||||
// Grant loot & track kill
|
||||
if(!artificial && killer != null && killer.isPlayer()) {
|
||||
Player player = (Player)killer;
|
||||
|
||||
if(!isPlayerPlaced()) {
|
||||
// Track assists
|
||||
for(EntityAttack recentAttack : recentAttacks) {
|
||||
Entity attacker = recentAttack.getAttacker();
|
||||
|
||||
if(attacker != player && attacker.isPlayer()) {
|
||||
((Player)attacker).getStatistics().trackAssist(config);
|
||||
}
|
||||
}
|
||||
|
||||
player.getStatistics().trackKill(config);
|
||||
}
|
||||
|
||||
EntityLoot loot = getRandomLoot(player, cause.getWeapon());
|
||||
|
||||
if(loot != null) {
|
||||
Item item = loot.getItem();
|
||||
|
||||
if(!item.isAir()) {
|
||||
player.getInventory().addItem(item, loot.getQuantity(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -191,6 +216,20 @@ public class Npc extends Entity {
|
|||
return maxHealth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDefense(EntityAttack attack) {
|
||||
Entity attacker = attack.getAttacker();
|
||||
Player player = attacker != null && attacker.isPlayer() ? (Player)attacker : null;
|
||||
|
||||
// Full defense if block is mounted and is protected
|
||||
if(isMounted() && zone.isBlockProtected(mountBlock.getX(), mountBlock.getY(), player)) {
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
// Otherwise, calculate defense
|
||||
return getBaseDefense(attack.getDamageType()) + activeDefenses.getOrDefault(attack.getDamageType(), 0F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getStatusConfig() {
|
||||
Map<String, Object> config = super.getStatusConfig();
|
||||
|
@ -229,37 +268,6 @@ public class Npc extends Entity {
|
|||
return config;
|
||||
}
|
||||
|
||||
public Vector2i getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void attack(Player attacker, Item weapon) {
|
||||
// Prevent damage if this entity is mounted and its mount is protected
|
||||
if(!attacker.isGodMode() && isMounted() && zone.isBlockProtected(mountBlock.getX(), mountBlock.getY(), attacker)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Pair<Item, Long> recentAttack = recentAttacks.get(attacker);
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
// Reject the attack if the player already attacked this entity recently
|
||||
if(!attacker.isGodMode() && recentAttack != null && now < recentAttack.getLast() + ATTACK_INVINCIBLE_TIME) {
|
||||
return;
|
||||
}
|
||||
|
||||
float damage = attacker.isGodMode() ? 9999 : calculateDamage(weapon.getDamage(), weapon.getDamageType());
|
||||
damage(damage, attacker);
|
||||
recentAttacks.put(attacker, new Pair<>(weapon, now));
|
||||
}
|
||||
|
||||
public float calculateDamage(float baseDamage, DamageType type) {
|
||||
return baseDamage * (1 - getDefense(type));
|
||||
}
|
||||
|
||||
public Collection<Pair<Item, Long>> getRecentAttacks() {
|
||||
return Collections.unmodifiableCollection(recentAttacks.values());
|
||||
}
|
||||
|
||||
public void setDefense(DamageType type, float amount) {
|
||||
if(amount == 0) {
|
||||
activeDefenses.remove(type);
|
||||
|
@ -268,21 +276,11 @@ public class Npc extends Entity {
|
|||
}
|
||||
}
|
||||
|
||||
public float getDefense(DamageType type) {
|
||||
return getDefense(type, true);
|
||||
}
|
||||
|
||||
public float getDefense(DamageType type, boolean includeBaseDefense) {
|
||||
return (includeBaseDefense ? getBaseDefense(type) : 0) + activeDefenses.getOrDefault(type, 0F);
|
||||
}
|
||||
|
||||
public boolean isTransient() {
|
||||
return !isGuard() && !isMounted();
|
||||
return !isGuard() && !isMounted() && !persist;
|
||||
}
|
||||
|
||||
public EntityLoot getRandomLoot(Player awardee) {
|
||||
Item weapon = awardee.getHeldItem();
|
||||
|
||||
public EntityLoot getRandomLoot(Player awardee, Item weapon) {
|
||||
if(isOwnedBy(awardee)) {
|
||||
return placedLoot.next();
|
||||
} else if(lootByWeapon.containsKey(weapon)) {
|
||||
|
@ -372,6 +370,18 @@ public class Npc extends Entity {
|
|||
return target;
|
||||
}
|
||||
|
||||
public void setArtificial(boolean artificial) {
|
||||
this.artificial = artificial;
|
||||
}
|
||||
|
||||
public boolean isArtificial() {
|
||||
return artificial;
|
||||
}
|
||||
|
||||
public boolean isPersistent() {
|
||||
return persist;
|
||||
}
|
||||
|
||||
public void setSpeed(float speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
@ -403,15 +413,15 @@ public class Npc extends Entity {
|
|||
int tY = y + oY;
|
||||
boolean blocked = zone.isBlockSolid(tX, tY) || (oX != 0 && zone.isBlockSolid(tX, y)) || (oY != 0 && zone.isBlockSolid(x, tY));
|
||||
|
||||
if(size.getX() > 1) {
|
||||
int additionalWidth = size.getX() - 1;
|
||||
if(sizeX > 1) {
|
||||
int additionalWidth = sizeX - 1;
|
||||
blocked = blocked || zone.isBlockSolid(tX + additionalWidth, tY)
|
||||
|| (oX != 0 && zone.isBlockSolid(tX + additionalWidth, y))
|
||||
|| (oY != 0 && zone.isBlockSolid(x + additionalWidth, tY));
|
||||
}
|
||||
|
||||
if(size.getY() > 1) {
|
||||
int additionalHeight = size.getY() - 1;
|
||||
if(sizeY > 1) {
|
||||
int additionalHeight = sizeY - 1;
|
||||
blocked = blocked || zone.isBlockSolid(tX, tY - additionalHeight)
|
||||
|| (oX != 0 && zone.isBlockSolid(tX, y - additionalHeight))
|
||||
|| (oY != 0 && zone.isBlockSolid(x, tY - additionalHeight));
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package brainwine.gameserver.entity.npc;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.entity.EntityConfig;
|
||||
|
||||
/**
|
||||
* Storage data for persistent non-player characters.
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class NpcData {
|
||||
|
||||
private EntityConfig type;
|
||||
private String name;
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
@JsonCreator
|
||||
public NpcData(@JsonProperty(value = "type", required = true) EntityConfig type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public NpcData(Npc npc) {
|
||||
this.type = npc.getConfig();
|
||||
this.name = npc.getName();
|
||||
this.x = npc.getBlockX();
|
||||
this.y = npc.getBlockY();
|
||||
}
|
||||
|
||||
public EntityConfig getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.behavior;
|
||||
package brainwine.gameserver.entity.npc.behavior;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
|
@ -7,26 +7,26 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|||
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
|
||||
|
||||
import brainwine.gameserver.behavior.composed.CrawlerBehavior;
|
||||
import brainwine.gameserver.behavior.composed.DiggerBehavior;
|
||||
import brainwine.gameserver.behavior.composed.FlyerBehavior;
|
||||
import brainwine.gameserver.behavior.composed.WalkerBehavior;
|
||||
import brainwine.gameserver.behavior.parts.ClimbBehavior;
|
||||
import brainwine.gameserver.behavior.parts.DigBehavior;
|
||||
import brainwine.gameserver.behavior.parts.EruptionAttackBehavior;
|
||||
import brainwine.gameserver.behavior.parts.FallBehavior;
|
||||
import brainwine.gameserver.behavior.parts.FlyBehavior;
|
||||
import brainwine.gameserver.behavior.parts.FlyTowardBehavior;
|
||||
import brainwine.gameserver.behavior.parts.FollowBehavior;
|
||||
import brainwine.gameserver.behavior.parts.IdleBehavior;
|
||||
import brainwine.gameserver.behavior.parts.RandomlyTargetBehavior;
|
||||
import brainwine.gameserver.behavior.parts.ReporterBehavior;
|
||||
import brainwine.gameserver.behavior.parts.ShielderBehavior;
|
||||
import brainwine.gameserver.behavior.parts.SpawnAttackBehavior;
|
||||
import brainwine.gameserver.behavior.parts.TurnBehavior;
|
||||
import brainwine.gameserver.behavior.parts.UnblockBehavior;
|
||||
import brainwine.gameserver.behavior.parts.WalkBehavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.composed.CrawlerBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.composed.DiggerBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.composed.FlyerBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.composed.WalkerBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.ClimbBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.DigBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.EruptionAttackBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.FallBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.FlyBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.FlyTowardBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.FollowBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.IdleBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.RandomlyTargetBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.ReporterBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.ShielderBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.SpawnAttackBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.TurnBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.UnblockBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.WalkBehavior;
|
||||
|
||||
/**
|
||||
* Heavily based on Deepworld's original "rubyhave" (ha ha very punny) behavior system.
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.behavior;
|
||||
package brainwine.gameserver.entity.npc.behavior;
|
||||
|
||||
import static brainwine.shared.LogMarkers.SERVER_MARKER;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.behavior;
|
||||
package brainwine.gameserver.entity.npc.behavior;
|
||||
|
||||
import java.util.Map;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.behavior;
|
||||
package brainwine.gameserver.entity.npc.behavior;
|
||||
|
||||
import static brainwine.shared.LogMarkers.SERVER_MARKER;
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
package brainwine.gameserver.behavior.composed;
|
||||
package brainwine.gameserver.entity.npc.behavior.composed;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.SelectorBehavior;
|
||||
import brainwine.gameserver.behavior.parts.ClimbBehavior;
|
||||
import brainwine.gameserver.behavior.parts.FallBehavior;
|
||||
import brainwine.gameserver.behavior.parts.IdleBehavior;
|
||||
import brainwine.gameserver.behavior.parts.TurnBehavior;
|
||||
import brainwine.gameserver.behavior.parts.WalkBehavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.SelectorBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.ClimbBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.FallBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.IdleBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.TurnBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.WalkBehavior;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
|
||||
public class CrawlerBehavior extends SelectorBehavior {
|
|
@ -1,17 +1,17 @@
|
|||
package brainwine.gameserver.behavior.composed;
|
||||
package brainwine.gameserver.entity.npc.behavior.composed;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.SelectorBehavior;
|
||||
import brainwine.gameserver.behavior.parts.DigBehavior;
|
||||
import brainwine.gameserver.behavior.parts.FallBehavior;
|
||||
import brainwine.gameserver.behavior.parts.IdleBehavior;
|
||||
import brainwine.gameserver.behavior.parts.TurnBehavior;
|
||||
import brainwine.gameserver.behavior.parts.WalkBehavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.SelectorBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.DigBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.FallBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.IdleBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.TurnBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.WalkBehavior;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
|
||||
public class DiggerBehavior extends SelectorBehavior {
|
|
@ -1,15 +1,15 @@
|
|||
package brainwine.gameserver.behavior.composed;
|
||||
package brainwine.gameserver.entity.npc.behavior.composed;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.SelectorBehavior;
|
||||
import brainwine.gameserver.behavior.parts.FlyBehavior;
|
||||
import brainwine.gameserver.behavior.parts.FlyTowardBehavior;
|
||||
import brainwine.gameserver.behavior.parts.IdleBehavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.SelectorBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.FlyBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.FlyTowardBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.IdleBehavior;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
|
||||
public class FlyerBehavior extends SelectorBehavior {
|
|
@ -1,16 +1,16 @@
|
|||
package brainwine.gameserver.behavior.composed;
|
||||
package brainwine.gameserver.entity.npc.behavior.composed;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.SelectorBehavior;
|
||||
import brainwine.gameserver.behavior.parts.FallBehavior;
|
||||
import brainwine.gameserver.behavior.parts.IdleBehavior;
|
||||
import brainwine.gameserver.behavior.parts.TurnBehavior;
|
||||
import brainwine.gameserver.behavior.parts.WalkBehavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.SelectorBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.FallBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.IdleBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.TurnBehavior;
|
||||
import brainwine.gameserver.entity.npc.behavior.parts.WalkBehavior;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
|
||||
public class WalkerBehavior extends SelectorBehavior {
|
|
@ -1,11 +1,11 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.FacingDirection;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
|
||||
public class ClimbBehavior extends Behavior {
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
|
||||
public class DigBehavior extends Behavior {
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -6,10 +6,10 @@ import com.fasterxml.jackson.annotation.JacksonInject;
|
|||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.EntityConfig;
|
||||
import brainwine.gameserver.entity.EntityStatus;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
import brainwine.gameserver.server.messages.EntityStatusMessage;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
import brainwine.gameserver.util.Vector2i;
|
|
@ -1,11 +1,11 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
|
||||
public class FallBehavior extends Behavior {
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
import brainwine.gameserver.util.Vector2i;
|
||||
|
||||
public class FlyBehavior extends Behavior {
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
|
@ -1,11 +1,11 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.FacingDirection;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
|
||||
public class FollowBehavior extends Behavior {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
@ -7,9 +7,9 @@ import com.fasterxml.jackson.annotation.JacksonInject;
|
|||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.FacingDirection;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
import brainwine.gameserver.util.Vector2i;
|
||||
|
||||
public class IdleBehavior extends Behavior {
|
|
@ -1,10 +1,10 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.player.Player;
|
||||
|
||||
public class RandomlyTargetBehavior extends Behavior {
|
||||
|
@ -31,7 +31,7 @@ public class RandomlyTargetBehavior extends Behavior {
|
|||
if(!entity.hasTarget()) {
|
||||
Player target = entity.getZone().getRandomPlayerInRange(entity.getX(), entity.getY(), range);
|
||||
|
||||
if(target != null && !target.isGodMode() && !target.isDead() && !entity.isOwnedBy(target) && (!blockable || entity.canSee(target))) {
|
||||
if(target != null && !target.isGodMode() && !target.isStealthy() && !target.isDead() && !entity.isOwnedBy(target) && (!blockable || entity.canSee(target))) {
|
||||
entity.setTarget(target);
|
||||
targetLockedAt = now;
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
|
||||
public class ReporterBehavior extends Behavior {
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
@ -9,11 +8,10 @@ import java.util.concurrent.ThreadLocalRandom;
|
|||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.EntityAttack;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
import brainwine.gameserver.item.DamageType;
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.util.Pair;
|
||||
|
||||
public class ShielderBehavior extends Behavior {
|
||||
|
||||
|
@ -32,11 +30,12 @@ public class ShielderBehavior extends Behavior {
|
|||
@Override
|
||||
public boolean behave() {
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<Pair<Item, Long>> recentAttacks = entity.getRecentAttacks();
|
||||
EntityAttack attack = entity.getMostRecentAttack();
|
||||
|
||||
if(!recentAttacks.isEmpty()) {
|
||||
if(attack != null) {
|
||||
lastAttackedAt = now;
|
||||
DamageType type = recentAttacks.stream().findFirst().get().getFirst().getDamageType();
|
||||
DamageType type = attack.getDamageType();
|
||||
|
||||
if(currentShield == null && now >= shieldStart + (recharge * 1000)) {
|
||||
if(defenses.contains(type)) {
|
||||
setShield(type);
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -6,13 +6,12 @@ import com.fasterxml.jackson.annotation.JacksonInject;
|
|||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.EntityConfig;
|
||||
import brainwine.gameserver.entity.EntityStatus;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
import brainwine.gameserver.server.messages.EntityStatusMessage;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
import brainwine.gameserver.util.Vector2i;
|
||||
|
||||
public class SpawnAttackBehavior extends Behavior {
|
||||
|
||||
|
@ -41,9 +40,8 @@ public class SpawnAttackBehavior extends Behavior {
|
|||
|
||||
if(npc) {
|
||||
// Spawn child at parent's location
|
||||
Vector2i size = entity.getSize();
|
||||
int spawnX = (int)(entity.getX() + (size.getX() / 2F));
|
||||
int spawnY = (int)(entity.getY() + (size.getY() / 2F));
|
||||
int spawnX = (int)(entity.getX() + (entity.getSizeX() / 2.0F));
|
||||
int spawnY = (int)(entity.getY() + (entity.getSizeX() / 2.0F));
|
||||
Npc child = new Npc(entity.getZone(), entityConfig);
|
||||
child.setOwner(entity);
|
||||
entity.addChild(child);
|
|
@ -1,11 +1,11 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.FacingDirection;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
|
||||
public class TurnBehavior extends Behavior {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
@ -6,9 +6,8 @@ import java.util.concurrent.ThreadLocalRandom;
|
|||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.util.Vector2i;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
|
||||
public class UnblockBehavior extends Behavior {
|
||||
|
@ -23,12 +22,11 @@ public class UnblockBehavior extends Behavior {
|
|||
@Override
|
||||
public boolean behave() {
|
||||
Zone zone = entity.getZone();
|
||||
Vector2i size = entity.getSize();
|
||||
Random random = ThreadLocalRandom.current();
|
||||
|
||||
for(int i = 0; i < rate; i++) {
|
||||
int x = (int)entity.getX() + random.nextInt(size.getX());
|
||||
int y = (int)entity.getY() - random.nextInt(size.getY());
|
||||
int x = (int)entity.getX() + random.nextInt(entity.getSizeX());
|
||||
int y = (int)entity.getY() - random.nextInt(entity.getSizeY());
|
||||
|
||||
if(zone.isChunkLoaded(x, y) && zone.getBlock(x, y).getFrontItem().isDiggable()) {
|
||||
zone.digBlock(x, y);
|
|
@ -1,12 +1,12 @@
|
|||
package brainwine.gameserver.behavior.parts;
|
||||
package brainwine.gameserver.entity.npc.behavior.parts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonInject;
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import brainwine.gameserver.behavior.Behavior;
|
||||
import brainwine.gameserver.entity.FacingDirection;
|
||||
import brainwine.gameserver.entity.npc.Npc;
|
||||
import brainwine.gameserver.entity.npc.behavior.Behavior;
|
||||
|
||||
public class WalkBehavior extends Behavior {
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package brainwine.gameserver.entity.player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import brainwine.gameserver.GameConfiguration;
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.ItemRegistry;
|
||||
import brainwine.gameserver.util.MapHelper;
|
||||
|
||||
/**
|
||||
* Utility class for player appearance related stuff.
|
||||
* Ghosts also have a random appearance, which is why it's here instead of in the player class.
|
||||
*/
|
||||
public class Appearance {
|
||||
|
||||
public static Map<String, Object> getRandomAppearance() {
|
||||
return getRandomAppearance(null);
|
||||
}
|
||||
|
||||
public static Map<String, Object> getRandomAppearance(Player player) {
|
||||
Map<String, Object> appearance = new HashMap<>();
|
||||
|
||||
for(AppearanceSlot slot : AppearanceSlot.values()) {
|
||||
// Skip if slot cannot be changed by players
|
||||
if(!slot.isChangeable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String category = slot.getCategory();
|
||||
|
||||
// Color handling
|
||||
if(slot.isColor()) {
|
||||
List<String> colors = getAvailableColors(slot, player);
|
||||
|
||||
// Change appearance to random color
|
||||
if(!colors.isEmpty()) {
|
||||
appearance.put(slot.getId(), colors.get((int)(Math.random() * colors.size())));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fetch list of items in this slot's category that the player owns
|
||||
List<Item> items = ItemRegistry.getItemsByCategory(category).stream()
|
||||
.filter(item -> item.isBase() || (player != null && player.getInventory().hasItem(item)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Change appearance to random clothing item
|
||||
if(!items.isEmpty()) {
|
||||
appearance.put(slot.getId(), items.get((int)(Math.random() * items.size())).getCode());
|
||||
}
|
||||
}
|
||||
|
||||
return appearance;
|
||||
}
|
||||
|
||||
public static List<String> getAvailableColors(AppearanceSlot slot) {
|
||||
return getAvailableColors(null);
|
||||
}
|
||||
|
||||
public static List<String> getAvailableColors(AppearanceSlot slot, Player player) {
|
||||
List<String> colors = new ArrayList<>();
|
||||
|
||||
// Return empty list if slot is not valid
|
||||
if(!slot.isColor()) {
|
||||
return colors;
|
||||
}
|
||||
|
||||
Map<String, Object> wardrobe = MapHelper.getMap(GameConfiguration.getBaseConfig(), "wardrobe", Collections.emptyMap());
|
||||
String category = slot.getCategory();
|
||||
|
||||
// Add base colors
|
||||
colors.addAll(MapHelper.getList(wardrobe, category, Collections.emptyList()));
|
||||
|
||||
// Add bonus colors
|
||||
if(player != null && player.getInventory().hasItem(ItemRegistry.getItem("accessories/makeup"))) {
|
||||
colors.addAll(MapHelper.getList(wardrobe, String.format("%s-bonus", category), Collections.emptyList()));
|
||||
}
|
||||
|
||||
return colors;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package brainwine.gameserver.entity.player;
|
||||
|
||||
public enum AppearanceSlot {
|
||||
|
||||
SKIN_COLOR("c*", "skin-color", true),
|
||||
HAIR_COLOR("h*", "hair-color", true),
|
||||
HAIR("h", "hair", true),
|
||||
FACIAL_HAIR("fh", "facialhair", true),
|
||||
TOPS("t", "tops", true),
|
||||
BOTTOMS("b", "bottoms", true),
|
||||
FOOTWEAR("fw", "footwear", true),
|
||||
HEADGEAR("hg", "headgear", true),
|
||||
FACIAL_GEAR("fg", "facialgear", true),
|
||||
FACIAL_GEAR_GLOW("fg*", "facialgear-glow"),
|
||||
SUIT("u", "suit"),
|
||||
TOPS_OVERLAY("to", "tops-overlay"),
|
||||
TOPS_OVERLAY_GLOW("to*", "tops-overlay-glow"),
|
||||
ARMS_OVERLAY("ao", "arms-overlay"),
|
||||
LEGS_OVERLAY("lo", "legs-overlay"),
|
||||
FOOTWEAR_OVERLAY("fo", "footwear-overlay");
|
||||
|
||||
private final String id;
|
||||
private final String category;
|
||||
private final boolean changeable;
|
||||
|
||||
private AppearanceSlot(String id, String category) {
|
||||
this(id, category, false);
|
||||
}
|
||||
|
||||
private AppearanceSlot(String id, String category, boolean changeable) {
|
||||
this.id = id;
|
||||
this.category = category;
|
||||
this.changeable = changeable;
|
||||
}
|
||||
|
||||
public static AppearanceSlot fromId(String id) {
|
||||
for(AppearanceSlot value : values()) {
|
||||
if(value.getId().equals(id)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public boolean isChangeable() {
|
||||
return changeable;
|
||||
}
|
||||
|
||||
public boolean isColor() {
|
||||
return id.endsWith("*");
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package brainwine.gameserver.entity.player;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum ClothingSlot {
|
||||
|
||||
HAIR("h"),
|
||||
FACIAL_HAIR("fh"),
|
||||
TOPS("t"),
|
||||
BOTTOMS("b"),
|
||||
FOOTWEAR("fw"),
|
||||
HEADGEAR("hg"),
|
||||
FACIAL_GEAR("fg"),
|
||||
SUIT("u"),
|
||||
TOPS_OVERLAY("to"),
|
||||
ARMS_OVERLAY("ao"),
|
||||
LEGS_OVERLAY("lo"),
|
||||
FOOTWEAR_OVERLAY("fo");
|
||||
|
||||
private final String id;
|
||||
|
||||
private ClothingSlot(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static ClothingSlot fromId(String id) {
|
||||
for(ClothingSlot value : values()) {
|
||||
if(value.getId().equals(id)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package brainwine.gameserver.entity.player;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum ColorSlot {
|
||||
|
||||
SKIN_COLOR("c*"),
|
||||
HAIR_COLOR("h*");
|
||||
|
||||
private final String id;
|
||||
|
||||
private ColorSlot(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static ColorSlot fromId(String id) {
|
||||
for(ColorSlot value : values()) {
|
||||
if(value.getId().equals(id)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package brainwine.gameserver.entity.player;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIncludeProperties;
|
||||
|
||||
@JsonIncludeProperties({"new_name", "previous_name", "date"})
|
||||
public class NameChange {
|
||||
|
||||
private String newName;
|
||||
private String previousName;
|
||||
private OffsetDateTime date;
|
||||
|
||||
@JsonCreator
|
||||
private NameChange() {}
|
||||
|
||||
public NameChange(String newName, String previousName) {
|
||||
this.newName = newName;
|
||||
this.previousName = previousName;
|
||||
date = OffsetDateTime.now();
|
||||
}
|
||||
|
||||
public String getNewName() {
|
||||
return newName;
|
||||
}
|
||||
|
||||
public String getPreviousName() {
|
||||
return previousName;
|
||||
}
|
||||
|
||||
public OffsetDateTime getDate() {
|
||||
return date;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue