Initial Commit
This commit is contained in:
commit
cc8e3f5b79
96 changed files with 5062 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Project exclude paths
|
||||||
|
/target/
|
||||||
|
/.idea/
|
82
pom.xml
Normal file
82
pom.xml
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<groupId>nl.iobyte</groupId>
|
||||||
|
<artifactId>themeparkconnector</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>vault-repo</id>
|
||||||
|
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>codemc-repo</id>
|
||||||
|
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||||
|
<layout>default</layout>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.socket</groupId>
|
||||||
|
<artifactId>socket.io-client</artifactId>
|
||||||
|
<version>1.0.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>nl.iobyte</groupId>
|
||||||
|
<artifactId>themepark</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.mkammerer.snowflake-id</groupId>
|
||||||
|
<artifactId>snowflake-id</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.tr7zw</groupId>
|
||||||
|
<artifactId>item-nbt-api</artifactId>
|
||||||
|
<version>2.8.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.milkbowl.vault</groupId>
|
||||||
|
<artifactId>VaultAPI</artifactId>
|
||||||
|
<version>1.7</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.2.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,103 @@
|
||||||
|
package nl.iobyte.themeparkconnector;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import net.milkbowl.vault.economy.Economy;
|
||||||
|
import nl.iobyte.themeparkconnector.api.ThemeParkConnectorAPI;
|
||||||
|
import nl.iobyte.themeparkconnector.api.config.enums.StorageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.commands.ThemeParkConnectorCommand;
|
||||||
|
import nl.iobyte.themeparkconnector.listeners.*;
|
||||||
|
import nl.iobyte.themeparkconnector.sbd.License;
|
||||||
|
import nl.iobyte.themeparkconnector.sbd.UpdateManager;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
public class ThemeParkConnector extends JavaPlugin {
|
||||||
|
|
||||||
|
private final static Gson gson = ThemeParkConnectorGson.getInstance();
|
||||||
|
|
||||||
|
private static ThemeParkConnector instance;
|
||||||
|
private final ThemeParkConnectorAPI api = new ThemeParkConnectorAPI();
|
||||||
|
private Economy econ = null;
|
||||||
|
private boolean disabling = false;
|
||||||
|
|
||||||
|
public void onEnable() {
|
||||||
|
if (!setupEconomy() ) {
|
||||||
|
Bukkit.getLogger().info(String.format("[%s] - No Vault dependency found!", getDescription().getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
instance = this;
|
||||||
|
api.enable();
|
||||||
|
|
||||||
|
//License stuff
|
||||||
|
new License(this, "TPP", api.getConfigurationManager().getString(StorageKey.LICENSE));
|
||||||
|
|
||||||
|
loadCommands();
|
||||||
|
loadListeners();
|
||||||
|
|
||||||
|
//Check Version
|
||||||
|
new UpdateManager(this, 4, UpdateManager.CheckType.SBDPLUGINS).handleResponse((versionResponse, version) -> {
|
||||||
|
if (versionResponse == UpdateManager.VersionResponse.FOUND_NEW) {
|
||||||
|
Bukkit.getLogger().warning("[ThemeParkConnector] There is a new version available! Curent: " + getDescription().getVersion() + " New: " + version);
|
||||||
|
} else if (versionResponse == UpdateManager.VersionResponse.LATEST) {
|
||||||
|
Bukkit.getLogger().info("[ThemeParkConnector] You are running the latest version [" + getDescription().getVersion() + "]!");
|
||||||
|
} else if (versionResponse == UpdateManager.VersionResponse.UNAVAILABLE) {
|
||||||
|
Bukkit.getLogger().severe("[ThemeParkConnector] Unable to perform an update check.");
|
||||||
|
}
|
||||||
|
}).check();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean setupEconomy() {
|
||||||
|
if(getServer().getPluginManager().getPlugin("Vault") == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
|
||||||
|
if (rsp == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
econ = rsp.getProvider();
|
||||||
|
return econ != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadCommands() {
|
||||||
|
new ThemeParkConnectorCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadListeners() {
|
||||||
|
PluginManager pm = Bukkit.getPluginManager();
|
||||||
|
pm.registerEvents(new PlayerListener(), this);
|
||||||
|
pm.registerEvents(new OperatorListener(), this);
|
||||||
|
pm.registerEvents(new AttractionListener(), this);
|
||||||
|
pm.registerEvents(new RideCountListener(), this);
|
||||||
|
pm.registerEvents(new TicketListener(), this);
|
||||||
|
pm.registerEvents(new RideOperatorListener(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDisable() {
|
||||||
|
disabling = true;
|
||||||
|
api.disable();
|
||||||
|
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Gson getGson() {
|
||||||
|
return gson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ThemeParkConnector getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Economy getEconomy() {
|
||||||
|
return econ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThemeParkConnectorAPI getAPI() {
|
||||||
|
return api;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDisabling() {
|
||||||
|
return disabling;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package nl.iobyte.themeparkconnector;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import nl.iobyte.themepark.api.attraction.enums.Status;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.adapter.OperatorItemAdapter;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.adapter.OperatorPanelAdapter;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItem;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorPanel;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.adapter.PacketPayloadAdapter;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.adapter.StatusAdapter;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacketPayload;
|
||||||
|
|
||||||
|
public class ThemeParkConnectorGson {
|
||||||
|
|
||||||
|
public static Gson getInstance() {
|
||||||
|
GsonBuilder builder = new GsonBuilder();
|
||||||
|
|
||||||
|
//Packet
|
||||||
|
builder.registerTypeAdapter(AbstractPacketPayload.class, new PacketPayloadAdapter())
|
||||||
|
.registerTypeAdapter(Status.class, new StatusAdapter());
|
||||||
|
|
||||||
|
//Operator
|
||||||
|
builder.registerTypeAdapter(OperatorPanel.class, new OperatorPanelAdapter())
|
||||||
|
.registerTypeAdapter(OperatorItem.class, new OperatorItemAdapter());
|
||||||
|
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.authentication.AuthenticationService;
|
||||||
|
import nl.iobyte.themeparkconnector.api.config.ConfigurationManager;
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.EventDispatcher;
|
||||||
|
import nl.iobyte.themeparkconnector.api.load.DataLoadService;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.NetworkingService;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.OperatorService;
|
||||||
|
import nl.iobyte.themeparkconnector.api.player.PlayerStateService;
|
||||||
|
import nl.iobyte.themeparkconnector.api.show.ShowService;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.StateService;
|
||||||
|
import nl.iobyte.themeparkconnector.logger.ThemeParkConnectorLogger;
|
||||||
|
|
||||||
|
public class ThemeParkConnectorAPI {
|
||||||
|
|
||||||
|
//Data
|
||||||
|
private ConfigurationManager configurationManager;
|
||||||
|
private final DataLoadService dataLoadService = new DataLoadService();
|
||||||
|
private final ShowService showService = new ShowService();
|
||||||
|
|
||||||
|
//ThemeParkConnector System
|
||||||
|
private final NetworkingService networkingService = new NetworkingService();
|
||||||
|
private final StateService stateService = new StateService();
|
||||||
|
private final PlayerStateService playerStateService = new PlayerStateService();
|
||||||
|
private AuthenticationService authenticationService;
|
||||||
|
|
||||||
|
//Attraction
|
||||||
|
private final OperatorService operatorService = new OperatorService();
|
||||||
|
|
||||||
|
//General
|
||||||
|
private EventDispatcher eventDispatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the API
|
||||||
|
*/
|
||||||
|
public void enable() {
|
||||||
|
eventDispatcher = new EventDispatcher(ThemeParkConnector.getInstance());
|
||||||
|
|
||||||
|
//Prepare Configuration
|
||||||
|
configurationManager = new ConfigurationManager(ThemeParkConnector.getInstance());
|
||||||
|
|
||||||
|
//Load data
|
||||||
|
dataLoadService.init();
|
||||||
|
authenticationService = new AuthenticationService();
|
||||||
|
networkingService.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable the API
|
||||||
|
*/
|
||||||
|
public void disable() {
|
||||||
|
try {
|
||||||
|
if (stateService.isConnected())
|
||||||
|
networkingService.stop();
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
ThemeParkConnectorLogger.toConsole("Bukkit already unloaded the networking classes, can't kill socket.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the show service
|
||||||
|
* @return ShowService
|
||||||
|
*/
|
||||||
|
public ShowService getShowService() {
|
||||||
|
return showService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the networking service
|
||||||
|
* @return NetworkingService
|
||||||
|
*/
|
||||||
|
public NetworkingService getNetworkingService() {
|
||||||
|
return networkingService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the configuration manager
|
||||||
|
* @return ConfigurationManager
|
||||||
|
*/
|
||||||
|
public ConfigurationManager getConfigurationManager() {
|
||||||
|
return configurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the state service
|
||||||
|
* @return StateService
|
||||||
|
*/
|
||||||
|
public StateService getStateService() {
|
||||||
|
return stateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the player state service
|
||||||
|
* @return PlayerStateService
|
||||||
|
*/
|
||||||
|
public PlayerStateService getPlayerStateService() {
|
||||||
|
return playerStateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data load service
|
||||||
|
* @return DataLoadService
|
||||||
|
*/
|
||||||
|
public DataLoadService getDataLoadService() {
|
||||||
|
return dataLoadService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the operator service
|
||||||
|
* @return OperatorService
|
||||||
|
*/
|
||||||
|
public OperatorService getOperatorService() {
|
||||||
|
return operatorService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get event dispatcher
|
||||||
|
* @return EventDispatcher
|
||||||
|
*/
|
||||||
|
public EventDispatcher getEventDispatcher() {
|
||||||
|
return eventDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get authentication service
|
||||||
|
* @return AuthenticationService
|
||||||
|
*/
|
||||||
|
public AuthenticationService getAuthenticationService() {
|
||||||
|
return authenticationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.authentication;
|
||||||
|
|
||||||
|
import de.mkammerer.snowflakeid.SnowflakeIdGenerator;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.authentication.objects.WeakConcurrentHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class AuthenticationService {
|
||||||
|
|
||||||
|
private final SnowflakeIdGenerator generator = SnowflakeIdGenerator.createDefault(42);
|
||||||
|
private final Map<UUID, String> tokens = new WeakConcurrentHashMap<>(ThemeParkConnector.getInstance(), 15 * 1000);
|
||||||
|
private final Map<UUID, String> attractions = new WeakConcurrentHashMap<>(ThemeParkConnector.getInstance(), 15 * 1000);
|
||||||
|
|
||||||
|
public String generateToken(UUID uuid, String id) {
|
||||||
|
long snowflake = generator.next();
|
||||||
|
|
||||||
|
//ID to Token and store Token
|
||||||
|
String token = Long.toString(snowflake);
|
||||||
|
tokens.put(uuid, token);
|
||||||
|
attractions.put(uuid, id);
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasToken(UUID uuid) {
|
||||||
|
return tokens.containsKey(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matchToken(UUID uuid, String token, String id) {
|
||||||
|
String str = tokens.get(uuid);
|
||||||
|
if(str == null || str.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!str.equals(token))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
str = attractions.get(uuid);
|
||||||
|
if(str == null || str.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!str.equals(id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
tokens.remove(uuid);
|
||||||
|
attractions.remove(uuid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.authentication.objects;
|
||||||
|
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Weak Concurrent HashMap Solution which stores the keys and values only for a specific amount of time, and then expires after that
|
||||||
|
* time.
|
||||||
|
*
|
||||||
|
* This HashMap uses the Bukkit scheduler for the cleanup.
|
||||||
|
*
|
||||||
|
* @author Vivekananthan M, Stijn Bannink
|
||||||
|
*
|
||||||
|
* @param <K> The key in the hashmap
|
||||||
|
* @param <V> The value in the hashmap
|
||||||
|
*/
|
||||||
|
public class WeakConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Map<K, Long> timeMap = new ConcurrentHashMap<>();
|
||||||
|
private final long expiryInMillis;
|
||||||
|
|
||||||
|
private Listener<K, V> listener;
|
||||||
|
private boolean mapAlive = true;
|
||||||
|
|
||||||
|
public WeakConcurrentHashMap(JavaPlugin plugin) {
|
||||||
|
this.expiryInMillis = 10000;
|
||||||
|
initialize(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeakConcurrentHashMap(JavaPlugin plugin, Listener<K, V> listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
this.expiryInMillis = 10000;
|
||||||
|
initialize(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeakConcurrentHashMap(JavaPlugin plugin, long expiryInMillis) {
|
||||||
|
this.expiryInMillis = expiryInMillis;
|
||||||
|
initialize(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeakConcurrentHashMap(JavaPlugin plugin, long expiryInMillis, Listener<K, V> listener) {
|
||||||
|
this.expiryInMillis = expiryInMillis;
|
||||||
|
this.listener = listener;
|
||||||
|
initialize(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize(JavaPlugin plugin) {
|
||||||
|
new CleanerRunnable().runTaskTimerAsynchronously(plugin, expiryInMillis / 2, expiryInMillis / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if trying to insert values into map after quiting
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public V put(K key, V value) {
|
||||||
|
if (!mapAlive) {
|
||||||
|
throw new IllegalStateException("WeakConcurrent Hashmap is no more alive.. Try creating a new one."); // No I18N
|
||||||
|
}
|
||||||
|
Date date = new Date();
|
||||||
|
timeMap.put(key, date.getTime());
|
||||||
|
V returnVal = super.put(key, value);
|
||||||
|
if (listener != null) {
|
||||||
|
listener.notifyOnAdd(key, value);
|
||||||
|
}
|
||||||
|
return returnVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if trying to insert values into map after quiting
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void putAll(Map<? extends K, ? extends V> m) {
|
||||||
|
if (!mapAlive) {
|
||||||
|
throw new IllegalStateException("WeakConcurrent Hashmap is no more alive.. Try creating a new one."); // No I18N
|
||||||
|
}
|
||||||
|
for (K key : m.keySet()) {
|
||||||
|
put(key, m.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if trying to insert values into map after quiting
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public V putIfAbsent(K key, V value) {
|
||||||
|
if (!mapAlive) {
|
||||||
|
throw new IllegalStateException("WeakConcurrent Hashmap is no more alive.. Try creating a new one."); // No I18N
|
||||||
|
}
|
||||||
|
if (!containsKey(key)) {
|
||||||
|
return put(key, value);
|
||||||
|
} else {
|
||||||
|
return get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should call this method when it's no longer required
|
||||||
|
*/
|
||||||
|
public void quitMap() {
|
||||||
|
mapAlive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAlive() {
|
||||||
|
return mapAlive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This thread performs the cleaning operation on the concurrent hashmap once in a specified interval. This wait interval is half of the
|
||||||
|
* time from the expiry time.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private class CleanerRunnable extends BukkitRunnable {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (mapAlive) cleanMap();
|
||||||
|
else cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanMap() {
|
||||||
|
long currentTime = new Date().getTime();
|
||||||
|
for (K key : timeMap.keySet()) {
|
||||||
|
if (currentTime > (timeMap.get(key) + expiryInMillis)) {
|
||||||
|
V value = remove(key);
|
||||||
|
timeMap.remove(key);
|
||||||
|
if (listener != null) {
|
||||||
|
listener.notifyOnRemoval(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Listener<K,V> {
|
||||||
|
void notifyOnAdd(K key, V value);
|
||||||
|
void notifyOnRemoval(K key, V value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,182 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.client;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.MessageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.packet.KickClientPacket;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ClientConnection {
|
||||||
|
|
||||||
|
//General
|
||||||
|
private final UUID uuid;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
//Connect
|
||||||
|
private boolean waitingForToken = false;
|
||||||
|
private boolean isConnected = false;
|
||||||
|
private String usedToken = null;
|
||||||
|
private String attraction;
|
||||||
|
private final List<Runnable> onConnect = new ArrayList<>();
|
||||||
|
private final List<Runnable> onDisconnect = new ArrayList<>();
|
||||||
|
private final Publisher publisher;
|
||||||
|
|
||||||
|
public ClientConnection(Player player) {
|
||||||
|
this.uuid = player.getUniqueId();
|
||||||
|
this.name = player.getName();
|
||||||
|
this.publisher = new Publisher(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Name of Client
|
||||||
|
* @return Client Name
|
||||||
|
*/
|
||||||
|
public String getOwnerName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get UUID of Client
|
||||||
|
* @return Client UUID
|
||||||
|
*/
|
||||||
|
public UUID getOwnerUUID() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Player
|
||||||
|
* @return Player instance
|
||||||
|
*/
|
||||||
|
public Player getPlayer() {
|
||||||
|
return Bukkit.getPlayer(getOwnerUUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if client is connected
|
||||||
|
* @return connection boolean
|
||||||
|
*/
|
||||||
|
public boolean isConnected() {
|
||||||
|
return isConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When client connection is opened
|
||||||
|
*/
|
||||||
|
public void onConnect() {
|
||||||
|
if(isConnected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
isConnected = true;
|
||||||
|
MessageKey.CLIENT_CONNECTION_OPEN.send(getPlayer());
|
||||||
|
for(Runnable runnable : onConnect)
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When client connection is closed
|
||||||
|
*/
|
||||||
|
public void onDisconnect() {
|
||||||
|
if(!isConnected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
isConnected = false;
|
||||||
|
usedToken = null;
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getOperatorService().stopOperating(uuid);
|
||||||
|
MessageKey.CLIENT_CONNECTION_CLOSED.send(getPlayer());
|
||||||
|
for(Runnable runnable : onDisconnect)
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get token used to connect
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getUsedToken() {
|
||||||
|
return usedToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set token used to connect
|
||||||
|
* @param token String
|
||||||
|
*/
|
||||||
|
public void setUsedToken(String token) {
|
||||||
|
usedToken = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get if client is waiting for token
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean isWaitingForToken() {
|
||||||
|
return waitingForToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if client is waiting for token
|
||||||
|
* @param waitingForToken boolean
|
||||||
|
*/
|
||||||
|
public void setWaitingForToken(boolean waitingForToken) {
|
||||||
|
this.waitingForToken = waitingForToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if client is waiting for token
|
||||||
|
* @param waitingForToken boolean
|
||||||
|
*/
|
||||||
|
public void setWaitingForToken(boolean waitingForToken, String attraction) {
|
||||||
|
setWaitingForToken(waitingForToken);
|
||||||
|
this.attraction = attraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publishURL() {
|
||||||
|
publisher.startClientSession(attraction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try generating url for client
|
||||||
|
*/
|
||||||
|
public void publishURL(String id) {
|
||||||
|
publisher.startClientSession(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the clients web client
|
||||||
|
*/
|
||||||
|
public void kick() {
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getNetworkingService().send(this, new KickClientPacket());
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getOperatorService().stopOperating(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When ClientConnection gets removed
|
||||||
|
*/
|
||||||
|
public void remove() {
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getNetworkingService().send(this, new KickClientPacket());
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getOperatorService().stopOperating(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add handler run on connect
|
||||||
|
* @param runnable Runnable
|
||||||
|
* @return ClientConnection
|
||||||
|
*/
|
||||||
|
public ClientConnection addOnConnectHandler(Runnable runnable) {
|
||||||
|
onConnect.add(runnable);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add handler run on disconnect
|
||||||
|
* @param runnable Runnable
|
||||||
|
* @return ClientConnection
|
||||||
|
*/
|
||||||
|
public ClientConnection addOnDisconnectHandler(Runnable runnable) {
|
||||||
|
onDisconnect.add(runnable);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.client;
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.chat.ClickEvent;
|
||||||
|
import net.md_5.bungee.api.chat.HoverEvent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
import nl.iobyte.themepark.scheduler.ThemeParkScheduler;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.config.enums.StorageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.MessageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.objects.AbstractState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.states.IdleState;
|
||||||
|
|
||||||
|
public class Publisher {
|
||||||
|
|
||||||
|
private final ClientConnection clientConnection;
|
||||||
|
|
||||||
|
public Publisher(ClientConnection clientConnection) {
|
||||||
|
this.clientConnection = clientConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to generate url
|
||||||
|
*/
|
||||||
|
public void startClientSession(String id) {
|
||||||
|
if(id == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Check if already connected
|
||||||
|
if (clientConnection.isConnected()) {
|
||||||
|
MessageKey.CLIENT_CONNECTION_EXISTS.send(clientConnection.getPlayer());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!clientConnection.isWaitingForToken())
|
||||||
|
MessageKey.CLIENT_GENERATE_TO_CONNECT.send(clientConnection.getPlayer());
|
||||||
|
|
||||||
|
//Check if state allows connections
|
||||||
|
AbstractState currentState = ThemeParkConnector.getInstance().getAPI().getStateService().getCurrentState();
|
||||||
|
if(!currentState.canClientConnect()) {
|
||||||
|
clientConnection.setWaitingForToken(true, id);
|
||||||
|
if(currentState instanceof IdleState)
|
||||||
|
ThemeParkScheduler.runAsync(() -> ThemeParkConnector.getInstance().getAPI().getNetworkingService().connectIfDown());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Sending waiting message
|
||||||
|
clientConnection.setWaitingForToken(true, id);
|
||||||
|
String token = ThemeParkConnector.getInstance().getAPI().getAuthenticationService().generateToken(clientConnection.getOwnerUUID(), id);
|
||||||
|
|
||||||
|
String url = ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getString(StorageKey.SOCKET_PANEL_URL);
|
||||||
|
url = url.replaceAll("%TOKEN%", token);
|
||||||
|
url = url.replaceAll("%ID%", id);
|
||||||
|
|
||||||
|
TextComponent message = new TextComponent(
|
||||||
|
MessageKey.CLIENT_CLICK_TO_CONNECT.getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
TextComponent[] hover = new TextComponent[]{
|
||||||
|
new TextComponent(
|
||||||
|
MessageKey.CLIENT_HOVER_TO_CONNECT.getMessage()
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
message.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url));
|
||||||
|
message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hover));
|
||||||
|
|
||||||
|
clientConnection.getPlayer().spigot().sendMessage(message);
|
||||||
|
clientConnection.setWaitingForToken(false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.client.objects;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.packet.NotificationPacket;
|
||||||
|
|
||||||
|
public class Notification {
|
||||||
|
|
||||||
|
private String title, message;
|
||||||
|
|
||||||
|
public Notification(String title, String message) {
|
||||||
|
this.title = title;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Title of Notification
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Title of Notification
|
||||||
|
* @param title String
|
||||||
|
*/
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Message of Notification
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Message of Notification
|
||||||
|
* @param message String
|
||||||
|
*/
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send Notification to client
|
||||||
|
* @param client ClientConnection
|
||||||
|
*/
|
||||||
|
public void send(ClientConnection client) {
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getNetworkingService().send(client, new NotificationPacket(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,252 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.config;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.api.config.objects.Configuration;
|
||||||
|
import nl.iobyte.themeparkconnector.api.config.enums.StorageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.api.config.enums.StorageLocation;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ConfigurationManager {
|
||||||
|
|
||||||
|
private final Map<StorageLocation, Configuration> locations = new HashMap<>();
|
||||||
|
|
||||||
|
public ConfigurationManager(Plugin plugin) {
|
||||||
|
for(StorageLocation location : StorageLocation.values())
|
||||||
|
locations.put(location, new Configuration(plugin, location.getName(), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get configuration instance belonging to a storage location
|
||||||
|
* @param location StorageLocation
|
||||||
|
* @return Configuration instance
|
||||||
|
*/
|
||||||
|
public Configuration getConfiguration(StorageLocation location) {
|
||||||
|
if(location == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return locations.get(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save specific storage location
|
||||||
|
* @param location StorageLocation
|
||||||
|
*/
|
||||||
|
public void save(StorageLocation location) {
|
||||||
|
if(location == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
getConfiguration(location).save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save all storage locations
|
||||||
|
*/
|
||||||
|
public void saveAll() {
|
||||||
|
for(Configuration configuration : locations.values())
|
||||||
|
configuration.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if configuration contains storage key
|
||||||
|
* @param key StorageKey
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public boolean contains(StorageKey key) {
|
||||||
|
if(key == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return contains(key.getLocation(), key.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if storage location contains path
|
||||||
|
* @param location StorageLocation
|
||||||
|
* @param path String
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public boolean contains(StorageLocation location, String path) {
|
||||||
|
if(location == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return getConfiguration(location).contains(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set value to StorageKey
|
||||||
|
* @param key StorageKey
|
||||||
|
* @param value Object to set StorageKey to
|
||||||
|
*/
|
||||||
|
public void set(StorageKey key, Object value) {
|
||||||
|
if(key == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
set(key.getLocation(), key.getPath(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set value to path in storage location
|
||||||
|
* @param location StorageLocation
|
||||||
|
* @param path String
|
||||||
|
* @param value Object to set path to
|
||||||
|
*/
|
||||||
|
public void set(StorageLocation location, String path, Object value) {
|
||||||
|
if(location == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
getConfiguration(location).set(path, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get object value of storage key
|
||||||
|
* @param key StorageKey
|
||||||
|
* @return Object
|
||||||
|
*/
|
||||||
|
public Object get(StorageKey key) {
|
||||||
|
if(key == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return get(key.getLocation(), key.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get object value of path in storage location
|
||||||
|
* @param location StorageLocation
|
||||||
|
* @param path Path
|
||||||
|
* @return Object
|
||||||
|
*/
|
||||||
|
public Object get(StorageLocation location, String path) {
|
||||||
|
if(location == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return getConfiguration(location).get(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get string value of storage key
|
||||||
|
* @param key StorageKey
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getString(StorageKey key) {
|
||||||
|
if(key == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return getString(key.getLocation(), key.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get string value of path in storage location
|
||||||
|
* @param location StorageLocation
|
||||||
|
* @param path Path
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getString(StorageLocation location, String path) {
|
||||||
|
if(location == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return getConfiguration(location).getString(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get int value of storage key
|
||||||
|
* @param key StorageKey
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public int getInt(StorageKey key) {
|
||||||
|
if(key == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return getInt(key.getLocation(), key.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get int value of path in storage location
|
||||||
|
* @param location StorageLocation
|
||||||
|
* @param path Path
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public int getInt(StorageLocation location, String path) {
|
||||||
|
if(location == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return getConfiguration(location).getInt(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get boolean value of storage key
|
||||||
|
* @param key StorageKey
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean getBoolean(StorageKey key) {
|
||||||
|
if(key == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return getBoolean(key.getLocation(), key.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get boolean value of path in storage location
|
||||||
|
* @param location StorageLocation
|
||||||
|
* @param path Path
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean getBoolean(StorageLocation location, String path) {
|
||||||
|
if(location == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return getConfiguration(location).getBoolean(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get string list value of storage key
|
||||||
|
* @param key StorageKey
|
||||||
|
* @return List<String>
|
||||||
|
*/
|
||||||
|
public List<String> getStringList(StorageKey key) {
|
||||||
|
if(key == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return getStringList(key.getLocation(), key.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get string list value of path in storage location
|
||||||
|
* @param location StorageLocation
|
||||||
|
* @param path Path
|
||||||
|
* @return List<String>
|
||||||
|
*/
|
||||||
|
public List<String> getStringList(StorageLocation location, String path) {
|
||||||
|
if(location == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return getConfiguration(location).getStringList(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get string list value of storage key
|
||||||
|
* @param key StorageKey
|
||||||
|
* @return List<String>
|
||||||
|
*/
|
||||||
|
public ConfigurationSection getSection(StorageKey key) {
|
||||||
|
if(key == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return getSection(key.getLocation(), key.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get string list value of path in storage location
|
||||||
|
* @param location StorageLocation
|
||||||
|
* @param path Path
|
||||||
|
* @return List<String>
|
||||||
|
*/
|
||||||
|
public ConfigurationSection getSection(StorageLocation location, String path) {
|
||||||
|
if(location == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return getConfiguration(location).getSection(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.config.enums;
|
||||||
|
|
||||||
|
public enum StorageKey {
|
||||||
|
|
||||||
|
//General
|
||||||
|
LICENSE(StorageLocation.SETTINGS, "license"),
|
||||||
|
ACTIONFOTO(StorageLocation.SETTINGS, "actionfoto"),
|
||||||
|
|
||||||
|
//Sign
|
||||||
|
SIGN_CONTROL_NAME(StorageLocation.SETTINGS, "sign.control.name"),
|
||||||
|
SIGN_CONTROL_TITLE(StorageLocation.SETTINGS, "sign.control.title"),
|
||||||
|
SIGN_SCAN_NAME(StorageLocation.SETTINGS, "sign.scan.name"),
|
||||||
|
SIGN_SCAN_TITLE(StorageLocation.SETTINGS, "sign.scan.title"),
|
||||||
|
|
||||||
|
//Socket
|
||||||
|
SOCKET_ID(StorageLocation.SETTINGS, "socket.id"),
|
||||||
|
SOCKET_URL(StorageLocation.SETTINGS, "socket.url"),
|
||||||
|
SOCKET_PANEL_URL(StorageLocation.SETTINGS, "socket.panel");
|
||||||
|
|
||||||
|
private final StorageLocation location;
|
||||||
|
private final String path;
|
||||||
|
StorageKey(StorageLocation location, String path) {
|
||||||
|
this.location = location;
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get storage location key is stored in
|
||||||
|
* @return StorageLocation
|
||||||
|
*/
|
||||||
|
public StorageLocation getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get path to value
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.config.enums;
|
||||||
|
|
||||||
|
public enum StorageLocation {
|
||||||
|
|
||||||
|
SETTINGS("settings.yml"),
|
||||||
|
MESSAGE("message.yml");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
StorageLocation(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns filename of StorageLocation
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.event;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.logger.ThemeParkConnectorLogger;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
|
public class EventDispatcher {
|
||||||
|
|
||||||
|
private final Plugin plugin;
|
||||||
|
|
||||||
|
public EventDispatcher(Plugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch Event without Callback
|
||||||
|
* @param event Event
|
||||||
|
*/
|
||||||
|
public void call(Event event) {
|
||||||
|
call(event, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch Event with Callback
|
||||||
|
* @param event Event
|
||||||
|
* @param callback Runnable
|
||||||
|
*/
|
||||||
|
public void call(Event event, Runnable callback) {
|
||||||
|
PluginManager pm = Bukkit.getPluginManager();
|
||||||
|
if(Bukkit.isPrimaryThread()) {
|
||||||
|
pm.callEvent(event);
|
||||||
|
if(callback != null)
|
||||||
|
callback.run();
|
||||||
|
} else {
|
||||||
|
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||||
|
pm.callEvent(event);
|
||||||
|
if(callback != null)
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.event.objects;
|
||||||
|
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
public class ChangeEvent<T> extends Event {
|
||||||
|
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
private final T old, current;
|
||||||
|
|
||||||
|
public ChangeEvent(T old, T current) {
|
||||||
|
this.old = old;
|
||||||
|
this.current = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getOld() {
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getCurrent() {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.event.objects;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
|
||||||
|
public class OperatorEvent<T> extends ChangeEvent<T> {
|
||||||
|
|
||||||
|
private final AttractionOperator operator;
|
||||||
|
|
||||||
|
public OperatorEvent(AttractionOperator operator, T old, T current) {
|
||||||
|
super(old, current);
|
||||||
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttractionOperator getOperator() {
|
||||||
|
return operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.event.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.objects.OperatorEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
|
||||||
|
public class OperatorConnectEvent extends OperatorEvent<ClientConnection> {
|
||||||
|
|
||||||
|
public OperatorConnectEvent(AttractionOperator operator, ClientConnection connection) {
|
||||||
|
super(operator, null, connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.event.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.objects.OperatorEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
|
||||||
|
public class OperatorDisconnectEvent extends OperatorEvent<ClientConnection> {
|
||||||
|
|
||||||
|
public OperatorDisconnectEvent(AttractionOperator operator, ClientConnection connection) {
|
||||||
|
super(operator, connection, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.event.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.objects.OperatorEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItem;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItemState;
|
||||||
|
|
||||||
|
public class OperatorStateEvent extends OperatorEvent<OperatorItemState> {
|
||||||
|
|
||||||
|
private final OperatorItem item;
|
||||||
|
private final String data;
|
||||||
|
|
||||||
|
public OperatorStateEvent(AttractionOperator operator, OperatorItem item, OperatorItemState old, OperatorItemState current, String data) {
|
||||||
|
super(operator, old, current);
|
||||||
|
this.item = item;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorItem getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.event.ticket;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.show.objects.Ticket;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class TicketScanEvent extends Event implements Cancellable {
|
||||||
|
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
|
||||||
|
private final UUID uuid;
|
||||||
|
private final Ticket ticket;
|
||||||
|
private final boolean valid;
|
||||||
|
|
||||||
|
private boolean cancel = false;
|
||||||
|
|
||||||
|
public TicketScanEvent(UUID uuid, Ticket ticket, boolean valid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.ticket = ticket;
|
||||||
|
this.valid = valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUUID() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ticket getTicket() {
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean b) {
|
||||||
|
cancel = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.load;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.load.interfaces.IDataLoader;
|
||||||
|
import nl.iobyte.themeparkconnector.api.load.objects.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DataLoadService {
|
||||||
|
|
||||||
|
private final List<IDataLoader> loaders = new ArrayList<>();
|
||||||
|
|
||||||
|
public DataLoadService() {
|
||||||
|
addLoader(new DatabaseLoader());
|
||||||
|
addLoader(new OperatorDataLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add IDataLoader
|
||||||
|
* @param dataLoader IDataLoader
|
||||||
|
*/
|
||||||
|
public void addLoader(IDataLoader dataLoader) {
|
||||||
|
loaders.add(dataLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call all IDataLoaders
|
||||||
|
*/
|
||||||
|
public void init() {
|
||||||
|
for(IDataLoader loader : loaders)
|
||||||
|
loader.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.load.interfaces;
|
||||||
|
|
||||||
|
public interface IDataLoader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when loading data
|
||||||
|
*/
|
||||||
|
void load();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.load.objects;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.ThemePark;
|
||||||
|
import nl.iobyte.themepark.api.database.DatabaseService;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.config.enums.StorageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.api.load.interfaces.IDataLoader;
|
||||||
|
|
||||||
|
public class DatabaseLoader implements IDataLoader {
|
||||||
|
|
||||||
|
public void load() {
|
||||||
|
DatabaseService service = ThemePark.getInstance().getAPI().getDatabaseService();
|
||||||
|
|
||||||
|
//Create MySQL Tables
|
||||||
|
service.execute(
|
||||||
|
"remote",
|
||||||
|
"CREATE TABLE IF NOT EXISTS ridecounts(uuid VARCHAR(255) NOT NULL, attraction_id VARCHAR(255) NOT NULL, year SMALLINT(2), month SMALLINT(2), week SMALLINT(2), day SMALLINT(2), count SMALLINT(2), UNIQUE(uuid, attraction_id, year, day))",
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
service.execute(
|
||||||
|
"remote",
|
||||||
|
"CREATE TABLE IF NOT EXISTS seats(id BIGINT(20) NOT NULL AUTO_INCREMENT, show_id VARCHAR(256) NOT NULL, vault_price VARCHAR(256) NOT NULL, date TIMESTAMP NOT NULL, seat INT(11) NOT NULL, uuid VARCHAR(256) NOT NULL, loaded TINYINT(1) DEFAULT 0, paid TINYINT(1) DEFAULT 0, UNIQUE(show_id, date, uuid), UNIQUE(show_id, seat, date), PRIMARY KEY(id))",
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
if(ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getBoolean(StorageKey.ACTIONFOTO)) {
|
||||||
|
service.execute(
|
||||||
|
"remote",
|
||||||
|
"CREATE TABLE IF NOT EXISTS actionfotos (id BIGINT(20) NOT NULL AUTO_INCREMENT, uuid VARCHAR(256) NOT NULL, ride VARCHAR(256) NOT NULL, base64 BLOB NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(), UNIQUE(uuid, ride), PRIMARY KEY(id))",
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,250 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.load.objects;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.ThemePark;
|
||||||
|
import nl.iobyte.themepark.api.ThemeParkAPI;
|
||||||
|
import nl.iobyte.themepark.api.config.objects.Configuration;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.load.interfaces.IDataLoader;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.OperatorService;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItem;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItemState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorPanel;
|
||||||
|
import nl.iobyte.themeparkconnector.logger.ThemeParkConnectorLogger;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class OperatorDataLoader implements IDataLoader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when loading data
|
||||||
|
*/
|
||||||
|
public void load() {
|
||||||
|
ThemeParkAPI api = ThemePark.getInstance().getAPI();
|
||||||
|
|
||||||
|
File folder = new File(ThemeParkConnector.getInstance().getDataFolder(), "panels");
|
||||||
|
if(!folder.exists()) {
|
||||||
|
if (!folder.mkdirs()) {
|
||||||
|
ThemeParkConnectorLogger.toConsole("Unable to create 'panels' folder");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> keys = new HashSet<>(api.getAttractionService().getRegions().keySet());
|
||||||
|
if(!new File(folder, "templates").exists()) {
|
||||||
|
keys.add("templates");
|
||||||
|
} else {
|
||||||
|
loadPanels(api, "panels/templates");
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
if(files != null && files.length != 0) {
|
||||||
|
for (File file : files) {
|
||||||
|
String name = file.getName();
|
||||||
|
if (name.equals("templates"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (file.isFile()) {
|
||||||
|
ThemeParkConnectorLogger.toConsole("File '" + name + "' in 'panels' folder not allowed");
|
||||||
|
if (!file.delete())
|
||||||
|
ThemeParkConnectorLogger.toConsole("Unable to delete file '" + name + "' in 'panels' folder");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!api.getAttractionService().hasRegion(name)) {
|
||||||
|
ThemeParkConnectorLogger.toConsole("Folder '" + name + "' in 'panels' folder not allowed");
|
||||||
|
if (!file.delete())
|
||||||
|
ThemeParkConnectorLogger.toConsole("Unable to delete folder '" + name + "' in 'panels' folder");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
keys.remove(name);
|
||||||
|
loadPanels(api, "panels/"+name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(String name : keys) {
|
||||||
|
if (!new File(ThemeParkConnector.getInstance().getDataFolder(), "panels/" + name).mkdir()) {
|
||||||
|
ThemeParkConnectorLogger.toConsole("Unable to create folder '" + name + "' in 'panels' folder");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadPanels(api, "panels/"+name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(String id : ThemeParkConnector.getInstance().getAPI().getOperatorService().getPanels().keySet()) {
|
||||||
|
if(api.getAttractionService().hasAttraction(id))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getOperatorService().removePanel(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadPanels(ThemeParkAPI api, String path) {
|
||||||
|
File folder = new File(ThemeParkConnector.getInstance().getDataFolder(), path);
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
|
||||||
|
Set<String> keys;
|
||||||
|
if(folder.getName().equals("templates")) {
|
||||||
|
keys = new HashSet<>();
|
||||||
|
} else {
|
||||||
|
keys = new HashSet<>(api.getAttractionService().getRegion(folder.getName()).getAttractions().keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(files != null && files.length != 0) {
|
||||||
|
for (File file : files) {
|
||||||
|
String name = file.getName();
|
||||||
|
if (!file.isFile()) {
|
||||||
|
ThemeParkConnectorLogger.toConsole("Folder '" + name + "' in '" + path + "' folder not allowed");
|
||||||
|
if (!file.delete())
|
||||||
|
ThemeParkConnectorLogger.toConsole("Unable to delete folder '" + name + "' in 'panels' folder");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name.endsWith(".yml") && !name.endsWith(".json")) {
|
||||||
|
ThemeParkConnectorLogger.toConsole("Extension of file '" + name + "' in '" + path + "' folder not allowed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
keys.remove(name.replaceAll("(.json|.yml)", ""));
|
||||||
|
loadPanel(api, path, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(String name : keys)
|
||||||
|
loadPanel(api, path, name+".yml");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadPanel(ThemeParkAPI api, String path, String id) {
|
||||||
|
Configuration configuration = new Configuration(ThemeParkConnector.getInstance(), path+"/"+id, false);
|
||||||
|
id = id.replaceAll("(.json|.yml)", "");
|
||||||
|
if(configuration.contains("template")) {
|
||||||
|
loadTemplatedPanel(ThemeParkConnector.getInstance().getAPI().getOperatorService(), configuration, id);
|
||||||
|
if(!api.getAttractionService().hasAttraction(id) || !ThemeParkConnector.getInstance().getAPI().getOperatorService().hasPanel(id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
String permission = configuration.getString("permission");
|
||||||
|
String start_command = configuration.getString("start_command");
|
||||||
|
String stop_command = configuration.getString("stop_command");
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getOperatorService().addOperator(new AttractionOperator(
|
||||||
|
id,
|
||||||
|
permission,
|
||||||
|
start_command,
|
||||||
|
stop_command
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!configuration.contains("items"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ConfigurationSection items = configuration.getSection("items");
|
||||||
|
if(items == null || items.getKeys(false).isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ConfigurationSection states;
|
||||||
|
OperatorPanel panel = new OperatorPanel(id);
|
||||||
|
for(String item_id : items.getKeys(false)) {
|
||||||
|
path = "items."+item_id;
|
||||||
|
String name = configuration.getString(path+".name");
|
||||||
|
String active_state = configuration.getString(path+".active_state");
|
||||||
|
if(!configuration.contains(path+".states"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
states = configuration.getSection(path+".states");
|
||||||
|
if(states == null || states.getKeys(false).isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
OperatorItem item = new OperatorItem(item_id, name, active_state);
|
||||||
|
for(String state_id : states.getKeys(false)) {
|
||||||
|
path = "items." + item_id + ".states." + state_id;
|
||||||
|
name = configuration.getString(path+".name");
|
||||||
|
String cover = configuration.getString(path+".cover");
|
||||||
|
String command = configuration.getString(path+".command");
|
||||||
|
|
||||||
|
String text_color = configuration.getString(path+".text_color");
|
||||||
|
String background_color = configuration.getString(path+".background_color");
|
||||||
|
if(text_color != null && !text_color.isEmpty() && background_color != null && !background_color.isEmpty()) {
|
||||||
|
boolean glow = configuration.getBoolean(path+".glow");
|
||||||
|
|
||||||
|
item.addState(new OperatorItemState(state_id, name, cover, command, text_color, background_color, glow));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.addState(new OperatorItemState(state_id, name, cover, command));
|
||||||
|
}
|
||||||
|
|
||||||
|
panel.addItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(panel.getItems().size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getOperatorService().addPanel(panel);
|
||||||
|
if(!api.getAttractionService().hasAttraction(id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
String permission = configuration.getString("permission");
|
||||||
|
String start_command = configuration.getString("start_command");
|
||||||
|
String stop_command = configuration.getString("stop_command");
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getOperatorService().addOperator(new AttractionOperator(
|
||||||
|
id,
|
||||||
|
permission,
|
||||||
|
start_command,
|
||||||
|
stop_command
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadTemplatedPanel(OperatorService service, Configuration configuration, String id) {
|
||||||
|
OperatorPanel panel = service.getPanel(configuration.getString("template"));
|
||||||
|
if(panel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!configuration.contains("items"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ConfigurationSection items = configuration.getSection("items");
|
||||||
|
if(items == null || items.getKeys(false).isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
String path;
|
||||||
|
Map<String, String> map;
|
||||||
|
ConfigurationSection states;
|
||||||
|
Map<String, Map<String, String>> commandMap = new LinkedHashMap<>();
|
||||||
|
for(String item_id : items.getKeys(false)) {
|
||||||
|
path = "items."+item_id;
|
||||||
|
if(!configuration.contains(path+".states"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
states = configuration.getSection("states");
|
||||||
|
if(states == null || states.getKeys(false).isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
map = new LinkedHashMap<>();
|
||||||
|
for(String state_id : items.getKeys(false)) {
|
||||||
|
path = "items." + item_id + ".states." + state_id;
|
||||||
|
String command = configuration.getString(path+".command");
|
||||||
|
|
||||||
|
map.put(state_id, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(map.size() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
commandMap.put(item_id, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(commandMap.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
service.addPanel(panel.copy(id, commandMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.message;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.config.enums.StorageLocation;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public enum MessageKey {
|
||||||
|
|
||||||
|
//Prefix
|
||||||
|
PREFIX("prefix"),
|
||||||
|
|
||||||
|
//Session
|
||||||
|
CLIENT_UNABLE_TO_CONNECT("client.connect.unable"),
|
||||||
|
CLIENT_GENERATE_TO_CONNECT("client.connect.generate"),
|
||||||
|
CLIENT_CLICK_TO_CONNECT("client.connect.click"),
|
||||||
|
CLIENT_HOVER_TO_CONNECT("client.connect.hover"),
|
||||||
|
|
||||||
|
//Connection
|
||||||
|
CLIENT_CONNECTION_EXISTS("client.connection.exists"),
|
||||||
|
CLIENT_CONNECTION_OPEN("client.connection.open"),
|
||||||
|
CLIENT_CONNECTION_CLOSED("client.connection.closed");
|
||||||
|
|
||||||
|
private final String path;
|
||||||
|
MessageKey(String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get path to message
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get and color message from config
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getMessage() {
|
||||||
|
String msg = Text.color(ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getString(StorageLocation.MESSAGE, path));
|
||||||
|
if(this != MessageKey.PREFIX)
|
||||||
|
msg = msg.replace("{prefix}", MessageKey.PREFIX.getMessage());
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send message with color to Player
|
||||||
|
* @param player Player
|
||||||
|
*/
|
||||||
|
public void send(Player player) {
|
||||||
|
player.sendMessage(getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.message;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
|
||||||
|
public class Text {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color text
|
||||||
|
* @param str String
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String color(String str) {
|
||||||
|
return ChatColor.translateAlternateColorCodes('&', str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strip text of color
|
||||||
|
* @param str String
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String strip(String str) {
|
||||||
|
return ChatColor.stripColor(color(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.scheduler.ThemeParkScheduler;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.handlers.ClientConnectivityHandler;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.handlers.ClientOperatorHandler;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.io.SocketConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.objects.INetworkingEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.enums.PacketChannel;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacket;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.PayloadHandler;
|
||||||
|
import nl.iobyte.themeparkconnector.logger.ThemeParkConnectorLogger;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class NetworkingService {
|
||||||
|
|
||||||
|
private final Set<INetworkingEvent> eventHandlers = new HashSet<>();
|
||||||
|
private final Map<UUID, ClientConnection> clientMap = new HashMap<>();
|
||||||
|
private final Map<String, List<PayloadHandler<?>>> packetHandlerMap = new HashMap<>();
|
||||||
|
private SocketConnector socketConnector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize SocketConnector
|
||||||
|
*/
|
||||||
|
public void init() {
|
||||||
|
if(socketConnector != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
socketConnector = new SocketConnector();
|
||||||
|
|
||||||
|
//Connect, Disconnect, Kick
|
||||||
|
ClientConnectivityHandler.load(this);
|
||||||
|
|
||||||
|
//Operator
|
||||||
|
ClientOperatorHandler.load(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Establish a socket connection if the connection is down
|
||||||
|
*/
|
||||||
|
public void connectIfDown() {
|
||||||
|
ThemeParkScheduler.runAsync(() -> socketConnector.setupConnection());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(ClientConnection client, AbstractPacket packet) {
|
||||||
|
for (INetworkingEvent event : getEvents())
|
||||||
|
event.onPacketSend(client, packet);
|
||||||
|
|
||||||
|
socketConnector.send(client, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get handler for packet and call it
|
||||||
|
* @param abstractPacket Received Packet
|
||||||
|
*/
|
||||||
|
public void triggerPacket(AbstractPacket abstractPacket) {
|
||||||
|
if (packetHandlerMap.get(abstractPacket.getChannel()) == null) {
|
||||||
|
ThemeParkConnectorLogger.toConsole("Unknown handler for packet channel " + abstractPacket.getChannel());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
packetHandlerMap.get(abstractPacket.getChannel()).forEach(handler -> handler.handle(abstractPacket));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerHandler(PacketChannel channel, PayloadHandler<?> handler) {
|
||||||
|
registerHandler(channel.toString(), handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link a handler to a packet type
|
||||||
|
* @param channel Channel of the packet
|
||||||
|
* @param handler Handler for the incoming data
|
||||||
|
*/
|
||||||
|
public void registerHandler(String channel, PayloadHandler<?> handler) {
|
||||||
|
List<PayloadHandler<?>> handlers = packetHandlerMap.getOrDefault(channel, new ArrayList<>());
|
||||||
|
handlers.add(handler);
|
||||||
|
packetHandlerMap.put(channel, handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Client from UUID
|
||||||
|
* @param uuid UUID of client
|
||||||
|
* @return ClientConnection instance
|
||||||
|
*/
|
||||||
|
public ClientConnection getClient(UUID uuid) {
|
||||||
|
if (clientMap.containsKey(uuid))
|
||||||
|
return clientMap.get(uuid);
|
||||||
|
|
||||||
|
Player player = Bukkit.getPlayer(uuid);
|
||||||
|
if (player == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return register(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all ClientConnections
|
||||||
|
* @return Collection of all ClientConnections
|
||||||
|
*/
|
||||||
|
public Collection<ClientConnection> getClients() {
|
||||||
|
return clientMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove client from the NetworkingService
|
||||||
|
* @param player Player's UUID
|
||||||
|
*/
|
||||||
|
public void remove(UUID player) {
|
||||||
|
if (!clientMap.containsKey(player))
|
||||||
|
return;
|
||||||
|
|
||||||
|
clientMap.remove(player).remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register client to the NetworkingService
|
||||||
|
* @param player Player
|
||||||
|
* @return ClientConnection instance
|
||||||
|
*/
|
||||||
|
public ClientConnection register(Player player) {
|
||||||
|
ClientConnection clientConnection = new ClientConnection(player);
|
||||||
|
clientMap.put(player.getUniqueId(), clientConnection);
|
||||||
|
return clientConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force the socket connection to close
|
||||||
|
*/
|
||||||
|
public void stop() {
|
||||||
|
socketConnector.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get networking events
|
||||||
|
* @return Set of NetworkingEvents
|
||||||
|
*/
|
||||||
|
public Set<INetworkingEvent> getEvents() {
|
||||||
|
return eventHandlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add event handler for networking activity
|
||||||
|
* @param events Networking event
|
||||||
|
*/
|
||||||
|
public void addEventHandler(INetworkingEvent events) {
|
||||||
|
eventHandlers.add(events);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.drivers;
|
||||||
|
|
||||||
|
import io.socket.client.Socket;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.io.SocketConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.objects.SocketDriver;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacket;
|
||||||
|
import nl.iobyte.themeparkconnector.logger.ThemeParkConnectorLogger;
|
||||||
|
|
||||||
|
public class ClientDriver extends SocketDriver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register event to handle incoming packets
|
||||||
|
* @param socket Socket
|
||||||
|
* @param connector SocketConnector
|
||||||
|
*/
|
||||||
|
public void boot(Socket socket, SocketConnector connector) {
|
||||||
|
socket.on("data", args -> {
|
||||||
|
try {
|
||||||
|
AbstractPacket packet = ThemeParkConnector.getGson().fromJson(args[0].toString(), AbstractPacket.class);
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getNetworkingService().triggerPacket(packet);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ThemeParkConnectorLogger.toConsole("Failed to parse incoming packet. The received data was: " + args[0].toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.drivers;
|
||||||
|
|
||||||
|
import io.socket.client.Manager;
|
||||||
|
import io.socket.client.Socket;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.ThemeParkConnectorAPI;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.MessageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.io.SocketConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.objects.SocketDriver;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.states.ConnectedState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.states.IdleState;
|
||||||
|
import nl.iobyte.themeparkconnector.logger.ThemeParkConnectorLogger;
|
||||||
|
|
||||||
|
public class SystemDriver extends SocketDriver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register what to do whit connection
|
||||||
|
* @param socket Socket
|
||||||
|
* @param connector SocketConnector
|
||||||
|
*/
|
||||||
|
public void boot(Socket socket, SocketConnector connector) {
|
||||||
|
//What to do when connecting
|
||||||
|
socket.on(Socket.EVENT_CONNECT, args -> {
|
||||||
|
ThemeParkConnectorAPI api = ThemeParkConnector.getInstance().getAPI();
|
||||||
|
api.getStateService().setState(new ConnectedState());
|
||||||
|
api.getPlayerStateService().start();
|
||||||
|
|
||||||
|
for(ClientConnection client : ThemeParkConnector.getInstance().getAPI().getNetworkingService().getClients()) {
|
||||||
|
if(!client.isWaitingForToken())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
client.publishURL();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//What to do when losing connection
|
||||||
|
socket.on(Socket.EVENT_DISCONNECT, args -> {
|
||||||
|
if(ThemeParkConnector.getInstance() == null || ThemeParkConnector.getInstance().isDisabling())
|
||||||
|
return;
|
||||||
|
|
||||||
|
cancelWaitForToken();
|
||||||
|
ThemeParkConnectorAPI api = ThemeParkConnector.getInstance().getAPI();
|
||||||
|
if(!(api.getStateService().getCurrentState() instanceof IdleState))
|
||||||
|
api.getStateService().setState(new IdleState("Disconnected from socket"));
|
||||||
|
|
||||||
|
api.getPlayerStateService().stop();
|
||||||
|
for(ClientConnection client : ThemeParkConnector.getInstance().getAPI().getNetworkingService().getClients()) {
|
||||||
|
if(!client.isConnected())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
client.onDisconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//What to do when can't connect
|
||||||
|
socket.on(Socket.EVENT_CONNECT_ERROR, args -> {
|
||||||
|
cancelWaitForToken();
|
||||||
|
ThemeParkConnectorAPI api = ThemeParkConnector.getInstance().getAPI();
|
||||||
|
api.getStateService().setState(new IdleState("Socket connection error"));
|
||||||
|
api.getPlayerStateService().stop();
|
||||||
|
|
||||||
|
ThemeParkConnectorLogger.toConsole(ThemeParkConnector.getGson().toJson(args));
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on(Manager.EVENT_ERROR, args -> ThemeParkConnectorLogger.toConsole(ThemeParkConnector.getGson().toJson(args)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel tokens for all people waiting for one
|
||||||
|
*/
|
||||||
|
private void cancelWaitForToken() {
|
||||||
|
if(ThemeParkConnector.getInstance() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(ClientConnection client : ThemeParkConnector.getInstance().getAPI().getNetworkingService().getClients()) {
|
||||||
|
if(!client.isWaitingForToken())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
client.setWaitingForToken(false);
|
||||||
|
MessageKey.CLIENT_UNABLE_TO_CONNECT.send(client.getPlayer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.handlers;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.NetworkingService;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.enums.PacketChannel;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.handlers.ClientConnectHandler;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.handlers.ClientDisconnectHandler;
|
||||||
|
|
||||||
|
public class ClientConnectivityHandler {
|
||||||
|
|
||||||
|
public static void load(NetworkingService service) {
|
||||||
|
service.registerHandler(PacketChannel.SERVER_IN_REGISTER_CLIENT, new ClientConnectHandler());
|
||||||
|
service.registerHandler(PacketChannel.SERVER_IN_UNREGISTER_CLIENT, new ClientDisconnectHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.handlers;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.NetworkingService;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.enums.PacketChannel;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.handlers.operator.ClientOperatorClickHandler;
|
||||||
|
|
||||||
|
public class ClientOperatorHandler {
|
||||||
|
|
||||||
|
public static void load(NetworkingService service) {
|
||||||
|
service.registerHandler(PacketChannel.SERVER_IN_OPERATOR_CLICK, new ClientOperatorClickHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.io;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.net.ProxySelector;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NullProxySelector extends ProxySelector {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Proxy> select(URI uri) {
|
||||||
|
if (uri == null) {
|
||||||
|
throw new IllegalArgumentException("uri must not be null");
|
||||||
|
}
|
||||||
|
return Collections.singletonList(Proxy.NO_PROXY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
|
||||||
|
ioe.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.io;
|
||||||
|
|
||||||
|
import io.socket.client.IO;
|
||||||
|
import io.socket.client.Socket;
|
||||||
|
import nl.iobyte.themepark.scheduler.ThemeParkScheduler;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.config.enums.StorageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.MessageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.drivers.ClientDriver;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.drivers.SystemDriver;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.objects.CertificateHelper;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.objects.SocketDriver;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacket;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.states.ConnectingState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.states.IdleState;
|
||||||
|
import nl.iobyte.themeparkconnector.logger.ThemeParkConnectorLogger;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
public class SocketConnector {
|
||||||
|
|
||||||
|
private static final SocketDriver[] drivers = {
|
||||||
|
new SystemDriver(),
|
||||||
|
new ClientDriver(),
|
||||||
|
};
|
||||||
|
|
||||||
|
private Socket socket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to establish connection to the ThemeParkConnector network
|
||||||
|
*/
|
||||||
|
public void setupConnection() {
|
||||||
|
if(!ThemeParkConnector.getInstance().getAPI().getStateService().getCurrentState().canConnect())
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Preparing socket.io settings
|
||||||
|
OkHttpClient okHttpClient = CertificateHelper.ignore(new OkHttpClient.Builder().proxySelector(new NullProxySelector())).build();
|
||||||
|
|
||||||
|
IO.Options opts = new IO.Options();
|
||||||
|
opts.callFactory = okHttpClient;
|
||||||
|
opts.reconnection = false;
|
||||||
|
opts.webSocketFactory = okHttpClient;
|
||||||
|
|
||||||
|
// authentication headers
|
||||||
|
opts.query = String.format(
|
||||||
|
"type=server&id=%s",
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getString(StorageKey.SOCKET_ID)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Setup socket.io connection
|
||||||
|
try {
|
||||||
|
socket = IO.socket(
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getString(StorageKey.SOCKET_URL),
|
||||||
|
opts
|
||||||
|
);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Register state to be connecting
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getStateService().setState(new ConnectingState());
|
||||||
|
|
||||||
|
//Schedule timeout check
|
||||||
|
ThemeParkScheduler.runSyncLater(() -> {
|
||||||
|
if (!(ThemeParkConnector.getInstance().getAPI().getStateService().getCurrentState() instanceof ConnectingState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cancelWaitingForToken();
|
||||||
|
ThemeParkConnectorLogger.toConsole("Connecting timed out.");
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getStateService().setState(new IdleState("Connecting to the socket timed out"));
|
||||||
|
}, 20 * 35);
|
||||||
|
|
||||||
|
|
||||||
|
//Register drivers
|
||||||
|
for(SocketDriver driver : drivers)
|
||||||
|
driver.boot(socket, this);
|
||||||
|
|
||||||
|
socket.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close connection with Socket
|
||||||
|
*/
|
||||||
|
public void disconnect() {
|
||||||
|
if(socket != null)
|
||||||
|
socket.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send Packet
|
||||||
|
* @param client ClientConnection
|
||||||
|
* @param packet AbstractPacket
|
||||||
|
*/
|
||||||
|
public void send(ClientConnection client, AbstractPacket packet) {
|
||||||
|
if(client == null || packet == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!ThemeParkConnector.getInstance().getAPI().getStateService().isConnected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!client.isConnected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
String data = client.getUsedToken() + "@" + ThemeParkConnector.getGson().toJson(packet);
|
||||||
|
socket.emit("data", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel tokens for all people waiting for one
|
||||||
|
*/
|
||||||
|
public void cancelWaitingForToken() {
|
||||||
|
for(ClientConnection client : ThemeParkConnector.getInstance().getAPI().getNetworkingService().getClients()) {
|
||||||
|
if(!client.isWaitingForToken())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
client.setWaitingForToken(false);
|
||||||
|
MessageKey.CLIENT_UNABLE_TO_CONNECT.send(client.getPlayer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.objects;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.logger.ThemeParkConnectorLogger;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
|
public class CertificateHelper {
|
||||||
|
|
||||||
|
public static OkHttpClient.Builder ignore(OkHttpClient.Builder builder) {
|
||||||
|
try {
|
||||||
|
// Create a trust manager that does not validate certificate chains
|
||||||
|
final TrustManager[] trustAllCerts = new TrustManager[] {
|
||||||
|
new X509TrustManager() {
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return new java.security.cert.X509Certificate[]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Install the all-trusting trust manager
|
||||||
|
final SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||||
|
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
|
||||||
|
// Create an ssl socket factory with our all-trusting manager
|
||||||
|
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
|
||||||
|
|
||||||
|
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
|
||||||
|
builder.hostnameVerifier((hostname, session) -> true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ThemeParkConnectorLogger.toConsole("Failed to middleman ssl, should probably be fine");
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.objects;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacket;
|
||||||
|
|
||||||
|
public interface INetworkingEvent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event to call when packet is being send
|
||||||
|
* @param client ClientConnection
|
||||||
|
* @param packet AbstractPacket
|
||||||
|
*/
|
||||||
|
default void onPacketSend(ClientConnection client, AbstractPacket packet) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event to call when the client opens the connection
|
||||||
|
* @param client ClientConnection
|
||||||
|
*/
|
||||||
|
default void onClientOpen(ClientConnection client) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event to call when the client closes the connection
|
||||||
|
* @param client ClientConnection
|
||||||
|
*/
|
||||||
|
default void onClientClose(ClientConnection client) {}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.objects;
|
||||||
|
|
||||||
|
import io.socket.client.Socket;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.io.SocketConnector;
|
||||||
|
|
||||||
|
public abstract class SocketDriver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to register stuff to the socket/connector
|
||||||
|
* @param socket Socket
|
||||||
|
* @param connector SocketConnector
|
||||||
|
*/
|
||||||
|
public abstract void boot(Socket socket, SocketConnector connector);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.packet;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.enums.PacketChannel;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacket;
|
||||||
|
|
||||||
|
public class KickClientPacket extends AbstractPacket {
|
||||||
|
|
||||||
|
public KickClientPacket() {
|
||||||
|
super(PacketChannel.CLIENT_KICK, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.packet;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.objects.Notification;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.payload.NotificationPayload;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.enums.PacketChannel;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacket;
|
||||||
|
|
||||||
|
public class NotificationPacket extends AbstractPacket {
|
||||||
|
|
||||||
|
public NotificationPacket(Notification notification) {
|
||||||
|
super(PacketChannel.CLIENT_NOTIFICATION, new NotificationPayload(notification));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.packet.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.enums.OperatorRequestReply;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.payload.operator.OperatorRequestReplyPayload;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.enums.PacketChannel;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacket;
|
||||||
|
|
||||||
|
public class OperatorRequestReplyPacket extends AbstractPacket {
|
||||||
|
|
||||||
|
public OperatorRequestReplyPacket(OperatorRequestReply requestReply, String message) {
|
||||||
|
super(PacketChannel.CLIENT_OPERATOR_REQUEST_REPLY, new OperatorRequestReplyPayload(
|
||||||
|
requestReply,
|
||||||
|
message,
|
||||||
|
null
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorRequestReplyPacket(OperatorRequestReply requestReply, String message, Object data) {
|
||||||
|
super(PacketChannel.CLIENT_OPERATOR_REQUEST_REPLY, new OperatorRequestReplyPayload(
|
||||||
|
requestReply,
|
||||||
|
message,
|
||||||
|
data
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.packet.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.payload.operator.OperatorStatePayload;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItemState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.enums.PacketChannel;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacket;
|
||||||
|
|
||||||
|
public class OperatorStatePacket extends AbstractPacket {
|
||||||
|
|
||||||
|
public OperatorStatePacket(String item_id, OperatorItemState state, String data) {
|
||||||
|
super(PacketChannel.CLIENT_OPERATOR_STATE, new OperatorStatePayload(
|
||||||
|
item_id,
|
||||||
|
state,
|
||||||
|
data
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.packet.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.api.attraction.enums.Status;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.payload.operator.OperatorStatePayload;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.payload.operator.StatusChangePayload;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItemState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.enums.PacketChannel;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacket;
|
||||||
|
|
||||||
|
public class StatusChangePacket extends AbstractPacket {
|
||||||
|
|
||||||
|
public StatusChangePacket(Status status) {
|
||||||
|
super(PacketChannel.CLIENT_ATTRACTION_STATE, new StatusChangePayload(
|
||||||
|
status
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.payload;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.objects.Notification;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacketPayload;
|
||||||
|
|
||||||
|
public class NotificationPayload extends AbstractPacketPayload {
|
||||||
|
|
||||||
|
private String title, message;
|
||||||
|
|
||||||
|
public NotificationPayload(Notification notification) {
|
||||||
|
this.title = notification.getTitle();
|
||||||
|
this.message = notification.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.payload.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.enums.OperatorRequestReply;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacketPayload;
|
||||||
|
|
||||||
|
public class OperatorRequestReplyPayload extends AbstractPacketPayload {
|
||||||
|
|
||||||
|
private OperatorRequestReply requestReply;
|
||||||
|
private String message;
|
||||||
|
private Object data;
|
||||||
|
|
||||||
|
public OperatorRequestReplyPayload(OperatorRequestReply requestReply, String message, Object data) {
|
||||||
|
this.requestReply = requestReply;
|
||||||
|
this.message = message;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.payload.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItemState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacketPayload;
|
||||||
|
|
||||||
|
public class OperatorStatePayload extends AbstractPacketPayload {
|
||||||
|
|
||||||
|
private String item_id;
|
||||||
|
private OperatorItemState state;
|
||||||
|
private String data;
|
||||||
|
|
||||||
|
public OperatorStatePayload(String item_id, OperatorItemState state, String data) {
|
||||||
|
this.item_id = item_id;
|
||||||
|
this.state = state;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.network.payload.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.api.attraction.enums.Status;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacketPayload;
|
||||||
|
|
||||||
|
public class StatusChangePayload extends AbstractPacketPayload {
|
||||||
|
|
||||||
|
private Status status;
|
||||||
|
|
||||||
|
public StatusChangePayload(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorPanel;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class OperatorService {
|
||||||
|
|
||||||
|
private final Map<String, AttractionOperator> operators = new HashMap<>();
|
||||||
|
private final Map<String, OperatorPanel> panels = new HashMap<>();
|
||||||
|
private final Map<UUID, String> operating = new HashMap<>();
|
||||||
|
|
||||||
|
public void addOperator(AttractionOperator operator) {
|
||||||
|
if(operator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
operators.put(operator.getAttractionID(), operator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasOperator(String id) {
|
||||||
|
return operators.containsKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttractionOperator getOperator(String id) {
|
||||||
|
return operators.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, AttractionOperator> getOperators() {
|
||||||
|
return operators;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPanel(OperatorPanel panel) {
|
||||||
|
if(panel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
panels.put(panel.getID(), panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPanel(String id) {
|
||||||
|
return panels.containsKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorPanel getPanel(String id) {
|
||||||
|
return panels.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, OperatorPanel> getPanels() {
|
||||||
|
return panels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePanel(String id) {
|
||||||
|
panels.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startOperating(UUID uuid, String id) {
|
||||||
|
AttractionOperator operator = getOperator(id);
|
||||||
|
if(operator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!operator.isAvailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
operator.setClient(uuid);
|
||||||
|
operating.put(uuid, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOperating(UUID uuid) {
|
||||||
|
return operating.containsKey(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopOperating(UUID uuid) {
|
||||||
|
String id = operating.remove(uuid);
|
||||||
|
if(id == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AttractionOperator operator = getOperator(id);
|
||||||
|
if(operator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
operator.setClient(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<UUID, String> getOperating() {
|
||||||
|
return operating;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.operator.adapter;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItem;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class OperatorItemAdapter implements JsonSerializer<OperatorItem> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes OperatorItem to json
|
||||||
|
* @param src OperatorItem
|
||||||
|
* @param typeOfSrc Type
|
||||||
|
* @param context JsonSerializationContext
|
||||||
|
* @return JsonElement
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(OperatorItem src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
JsonObject result = new JsonObject();
|
||||||
|
result.add("id", context.serialize(src.getID()));
|
||||||
|
result.add("name", context.serialize(src.getName()));
|
||||||
|
result.add("state", context.serialize(src.getActiveState()));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.operator.adapter;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorPanel;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class OperatorPanelAdapter implements JsonSerializer<OperatorPanel> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes OperatorPanel to json
|
||||||
|
* @param src OperatorPanel
|
||||||
|
* @param typeOfSrc Type
|
||||||
|
* @param context JsonSerializationContext
|
||||||
|
* @return JsonElement
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(OperatorPanel src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
JsonObject result = new JsonObject();
|
||||||
|
result.add("id", context.serialize(src.getID()));
|
||||||
|
result.add("items", context.serialize(src.getItems().values()));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.operator.enums;
|
||||||
|
|
||||||
|
public enum OperatorRequestReply {
|
||||||
|
|
||||||
|
ACCEPT,
|
||||||
|
DENY
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.operator.objects;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.ThemePark;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.ThemeParkConnectorAPI;
|
||||||
|
import nl.iobyte.themepark.api.attraction.objects.Attraction;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.operator.OperatorConnectEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.operator.OperatorDisconnectEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorPanel;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class AttractionOperator {
|
||||||
|
|
||||||
|
private UUID client_uuid;
|
||||||
|
private final String attraction_id, permission, start_command, stop_command;
|
||||||
|
|
||||||
|
public AttractionOperator(Attraction attraction, String permission, String start_command, String stop_command) {
|
||||||
|
this.attraction_id = attraction.getID();
|
||||||
|
this.permission = permission;
|
||||||
|
this.start_command = start_command;
|
||||||
|
this.stop_command = stop_command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttractionOperator(String attraction_id, String permission, String start_command, String stop_command) {
|
||||||
|
this.attraction_id = attraction_id;
|
||||||
|
this.permission = permission;
|
||||||
|
this.start_command = start_command;
|
||||||
|
this.stop_command = stop_command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getClientUUID() {
|
||||||
|
return client_uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientConnection getClientConnection() {
|
||||||
|
return ThemeParkConnector.getInstance().getAPI().getNetworkingService().getClient(client_uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canClientConnect(ClientConnection connection) {
|
||||||
|
if(connection == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(client_uuid != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(hasPermission())
|
||||||
|
return connection.getPlayer().hasPermission(permission);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClient(UUID client_uuid) {
|
||||||
|
ThemeParkConnectorAPI api = ThemeParkConnector.getInstance().getAPI();
|
||||||
|
if(client_uuid == null) {
|
||||||
|
api.getEventDispatcher().call(new OperatorDisconnectEvent(
|
||||||
|
this,
|
||||||
|
api.getNetworkingService().getClient(this.client_uuid)
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
api.getEventDispatcher().call(new OperatorConnectEvent(
|
||||||
|
this,
|
||||||
|
api.getNetworkingService().getClient(client_uuid)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.client_uuid = client_uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttractionID() {
|
||||||
|
return attraction_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Attraction getAttraction() {
|
||||||
|
return ThemePark.getInstance().getAPI().getAttractionService().getAttraction(attraction_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPermission() {
|
||||||
|
return permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPermission() {
|
||||||
|
return permission != null && !permission.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStartCommand() {
|
||||||
|
return start_command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStopCommand() {
|
||||||
|
return stop_command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return client_uuid == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorPanel getPanel() {
|
||||||
|
return ThemeParkConnector.getInstance().getAPI().getOperatorService().getPanel(attraction_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.operator.objects.panel;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.scheduler.ThemeParkScheduler;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class OperatorItem {
|
||||||
|
|
||||||
|
private final String id, name;
|
||||||
|
private final Map<String, OperatorItemState> states;
|
||||||
|
private String active_state;
|
||||||
|
|
||||||
|
public OperatorItem(String id, String name, String active_state) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.active_state = active_state;
|
||||||
|
this.states = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorItem(String id, String name, String active_state, Map<String, OperatorItemState> states) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.active_state = active_state;
|
||||||
|
this.states = states;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorItemState getActiveState() {
|
||||||
|
return getState(active_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActiveState(String active_state) {
|
||||||
|
this.active_state = active_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addState(OperatorItemState state) {
|
||||||
|
if(hasState(state.getID()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
states.put(state.getID(), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasState(String id) {
|
||||||
|
return states.containsKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorItemState getState(String id) {
|
||||||
|
return states.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void click() {
|
||||||
|
if(!states.containsKey(active_state))
|
||||||
|
return;
|
||||||
|
|
||||||
|
String cmd = getActiveState().getCommand();
|
||||||
|
if(cmd == null || cmd.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ThemeParkScheduler.runSync(() -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorItem copy(Map<String, String> commands) {
|
||||||
|
Map<String, OperatorItemState> states = new HashMap<>();
|
||||||
|
OperatorItemState state;
|
||||||
|
for(Map.Entry<String, OperatorItemState> entrySet : this.states.entrySet()) {
|
||||||
|
state = entrySet.getValue();
|
||||||
|
states.put(
|
||||||
|
entrySet.getKey(),
|
||||||
|
state.copy(commands.containsKey(entrySet.getKey()) ? commands.get(entrySet.getKey()) : state.getCommand())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OperatorItem(id, name, active_state, states);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.operator.objects.panel;
|
||||||
|
|
||||||
|
public class OperatorItemState {
|
||||||
|
|
||||||
|
private final String id, name, cover, text_color, background_color;
|
||||||
|
private final transient String command;
|
||||||
|
private final boolean glow;
|
||||||
|
|
||||||
|
public OperatorItemState(String id, String name, String cover, String command) {
|
||||||
|
if(command !=null && command.startsWith("/"))
|
||||||
|
command = command.replaceFirst("/", "");
|
||||||
|
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.cover = cover;
|
||||||
|
this.command = command;
|
||||||
|
this.text_color = "#fff";
|
||||||
|
this.background_color = "#666";
|
||||||
|
this.glow = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorItemState(String id, String name, String cover, String command, String text_color, String background_color, boolean glow) {
|
||||||
|
if(command !=null && command.startsWith("/"))
|
||||||
|
command = command.replaceFirst("/", "");
|
||||||
|
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.cover = cover;
|
||||||
|
this.command = command;
|
||||||
|
this.text_color = text_color;
|
||||||
|
this.background_color = background_color;
|
||||||
|
this.glow = glow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCover() {
|
||||||
|
return cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCommand() {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTextColor() {
|
||||||
|
return text_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBackgroundColor() {
|
||||||
|
return background_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGlowing() {
|
||||||
|
return glow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorItemState copy(String command) {
|
||||||
|
return new OperatorItemState(id, name, cover, command, text_color, background_color, glow);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.operator.objects.panel;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class OperatorPanel {
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
private final Map<String, OperatorItem> items;
|
||||||
|
|
||||||
|
public OperatorPanel(String id) {
|
||||||
|
this.id = id;
|
||||||
|
this.items = new LinkedHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorPanel(String id, Map<String, OperatorItem> items) {
|
||||||
|
this.id = id;
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItem(OperatorItem item) {
|
||||||
|
if(item == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(hasItem(item.getID()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
items.put(item.getID(), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItems(List<OperatorItem> items) {
|
||||||
|
for(OperatorItem item : items)
|
||||||
|
addItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItems(Map<String, OperatorItem> items) {
|
||||||
|
this.items.putAll(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasItem(String id) {
|
||||||
|
return items.containsKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorItem getItem(String id) {
|
||||||
|
return items.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, OperatorItem> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperatorPanel copy(String id, Map<String, Map<String, String>> commandMap) {
|
||||||
|
Map<String, OperatorItem> items = new LinkedHashMap<>();
|
||||||
|
OperatorItem item;
|
||||||
|
for(Map.Entry<String, OperatorItem> entrySet : this.items.entrySet()) {
|
||||||
|
item = entrySet.getValue();
|
||||||
|
items.put(
|
||||||
|
entrySet.getKey(),
|
||||||
|
item.copy(commandMap.containsKey(entrySet.getKey()) ? commandMap.get(entrySet.getKey()) : new LinkedHashMap<>())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OperatorPanel(id, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.adapter;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacketPayload;
|
||||||
|
import nl.iobyte.themeparkconnector.logger.ThemeParkConnectorLogger;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class PacketPayloadAdapter implements JsonSerializer<AbstractPacketPayload>, JsonDeserializer<AbstractPacketPayload> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes AbstractPacketPayload to json
|
||||||
|
* @param src AbstractPacketPayload
|
||||||
|
* @param typeOfSrc Type
|
||||||
|
* @param context JsonSerializationContext
|
||||||
|
* @return JsonElement
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(AbstractPacketPayload src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
JsonObject result = new JsonObject();
|
||||||
|
result.add("type", new JsonPrimitive(src.getClass().getName()));
|
||||||
|
result.add("payload", context.serialize(src, src.getClass()));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes AbstractPacketPayload to correct type
|
||||||
|
* @param element JsonElement
|
||||||
|
* @param typeOf Type
|
||||||
|
* @param context JsonDeserializationContext
|
||||||
|
* @return AbstractPacketPayload
|
||||||
|
* @throws JsonParseException Exception that might occur
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AbstractPacketPayload deserialize(JsonElement element, Type typeOf, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
try {
|
||||||
|
JsonObject object = element.getAsJsonObject();
|
||||||
|
String type = object.get("type").toString().replace("\"", "");
|
||||||
|
JsonElement payload = object.get("payload");
|
||||||
|
|
||||||
|
if(!type.contains("."))
|
||||||
|
type = "nl.iobyte.themeparkconnector.api.packet.payloads."+type;
|
||||||
|
|
||||||
|
return context.deserialize(payload, Class.forName(type));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.adapter;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
import nl.iobyte.themepark.api.attraction.enums.Status;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class StatusAdapter implements JsonSerializer<Status> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes Status to json
|
||||||
|
* @param src Status
|
||||||
|
* @param type Type
|
||||||
|
* @param context JsonSerializationContext
|
||||||
|
* @return JsonElement
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(Status src, Type type, JsonSerializationContext context) {
|
||||||
|
JsonObject result = new JsonObject();
|
||||||
|
result.add("id", context.serialize(src.getID()));
|
||||||
|
result.add("name", context.serialize(src.getName()));
|
||||||
|
result.add("hex", context.serialize(src.getHexColor()));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.enums;
|
||||||
|
|
||||||
|
public enum PacketChannel {
|
||||||
|
|
||||||
|
//Server in
|
||||||
|
SERVER_IN_REGISTER_CLIENT,
|
||||||
|
SERVER_IN_UNREGISTER_CLIENT,
|
||||||
|
|
||||||
|
//Server in Operator
|
||||||
|
SERVER_IN_OPERATOR_CLICK,
|
||||||
|
|
||||||
|
//Client
|
||||||
|
CLIENT_NOTIFICATION,
|
||||||
|
CLIENT_KICK,
|
||||||
|
|
||||||
|
//Client Operator
|
||||||
|
CLIENT_OPERATOR_REQUEST_REPLY,
|
||||||
|
CLIENT_OPERATOR_STATE,
|
||||||
|
CLIENT_ATTRACTION_STATE
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.handlers;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.ThemePark;
|
||||||
|
import nl.iobyte.themepark.api.attraction.objects.Attraction;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.ThemeParkConnectorAPI;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.Text;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.objects.INetworkingEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.packet.operator.OperatorRequestReplyPacket;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.enums.OperatorRequestReply;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.PayloadHandler;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.payloads.ClientConnectPayload;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ClientConnectHandler extends PayloadHandler<ClientConnectPayload> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player established connection with ThemeParkConnector
|
||||||
|
* @param payload ClientConnectPayload
|
||||||
|
*/
|
||||||
|
public void onReceive(ClientConnectPayload payload) {
|
||||||
|
ClientConnection connection = ThemeParkConnector.getInstance().getAPI().getNetworkingService().getClient(payload.getUUID());
|
||||||
|
if(connection == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ThemeParkConnectorAPI api = ThemeParkConnector.getInstance().getAPI();
|
||||||
|
if(!api.getAuthenticationService().matchToken(payload.getUUID(), payload.getToken(), payload.getAttractionID())) {
|
||||||
|
denyRequest(
|
||||||
|
api,
|
||||||
|
payload.getUUID(),
|
||||||
|
"Invalid token used to connect"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(api.getOperatorService().isOperating(payload.getUUID())) {
|
||||||
|
denyRequest(
|
||||||
|
api,
|
||||||
|
payload.getUUID(),
|
||||||
|
"You're already operating an attraction"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Attraction attraction = ThemePark.getInstance().getAPI().getAttractionService().getAttraction(payload.getAttractionID());
|
||||||
|
if(attraction == null) {
|
||||||
|
denyRequest(
|
||||||
|
api,
|
||||||
|
payload.getUUID(),
|
||||||
|
"Unable to find requested attraction"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AttractionOperator operator = api.getOperatorService().getOperator(payload.getAttractionID());
|
||||||
|
if(operator == null) {
|
||||||
|
denyRequest(
|
||||||
|
api,
|
||||||
|
payload.getUUID(),
|
||||||
|
"No operator found for attraction: " + Text.strip(attraction.getName())
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(!operator.canClientConnect(connection)) {
|
||||||
|
denyRequest(
|
||||||
|
api,
|
||||||
|
payload.getUUID(),
|
||||||
|
"You're not allowed to operate attraction: " + Text.strip(attraction.getName())
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
api.getOperatorService().startOperating(payload.getUUID(), payload.getAttractionID());
|
||||||
|
api.getNetworkingService().send(
|
||||||
|
api.getNetworkingService().getClient(payload.getUUID()),
|
||||||
|
new OperatorRequestReplyPacket(
|
||||||
|
OperatorRequestReply.ACCEPT,
|
||||||
|
"You're now operating attraction: " + Text.strip(attraction.getName()),
|
||||||
|
operator.getPanel()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
connection.setUsedToken(payload.getToken());
|
||||||
|
connection.onConnect();
|
||||||
|
|
||||||
|
for(INetworkingEvent event : ThemeParkConnector.getInstance().getAPI().getNetworkingService().getEvents())
|
||||||
|
event.onClientOpen(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void denyRequest(ThemeParkConnectorAPI api, UUID uuid, String message) {
|
||||||
|
api.getNetworkingService().send(
|
||||||
|
api.getNetworkingService().getClient(uuid),
|
||||||
|
new OperatorRequestReplyPacket(
|
||||||
|
OperatorRequestReply.DENY,
|
||||||
|
message
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.handlers;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.PayloadHandler;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.payloads.ClientDisconnectPayload;
|
||||||
|
|
||||||
|
public class ClientDisconnectHandler extends PayloadHandler<ClientDisconnectPayload> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player closed connection with ThemeParkConnector
|
||||||
|
* @param payload ClientDisconnectPayload
|
||||||
|
*/
|
||||||
|
public void onReceive(ClientDisconnectPayload payload) {
|
||||||
|
ClientConnection connection = ThemeParkConnector.getInstance().getAPI().getNetworkingService().getClient(payload.getUUID());
|
||||||
|
if(connection == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
connection.onDisconnect();
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getOperatorService().stopOperating(payload.getUUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.handlers.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.ThemeParkConnectorAPI;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.OperatorService;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItem;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorPanel;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.PayloadHandler;
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.payloads.operator.ClientOperatorClickPayload;
|
||||||
|
|
||||||
|
public class ClientOperatorClickHandler extends PayloadHandler<ClientOperatorClickPayload> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player click ThemeParkConnector Ride Operator
|
||||||
|
* @param payload ClientOperatorClickPayload
|
||||||
|
*/
|
||||||
|
public void onReceive(ClientOperatorClickPayload payload) {
|
||||||
|
ThemeParkConnectorAPI api = ThemeParkConnector.getInstance().getAPI();
|
||||||
|
ClientConnection connection = api.getNetworkingService().getClient(payload.getUUID());
|
||||||
|
if(connection == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OperatorService service = ThemeParkConnector.getInstance().getAPI().getOperatorService();
|
||||||
|
String attraction_id = service.getOperating().get(payload.getUUID());
|
||||||
|
if(attraction_id == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OperatorPanel panel = service.getPanel(attraction_id);
|
||||||
|
if(panel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OperatorItem item = panel.getItem(payload.getItemID());
|
||||||
|
if(item == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
item.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.objects;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.enums.PacketChannel;
|
||||||
|
|
||||||
|
public class AbstractPacket {
|
||||||
|
|
||||||
|
private String channel;
|
||||||
|
private AbstractPacketPayload data;
|
||||||
|
|
||||||
|
public AbstractPacket(PacketChannel channel, AbstractPacketPayload data) {
|
||||||
|
this(channel.toString(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractPacket(String channel, AbstractPacketPayload data) {
|
||||||
|
this.channel = channel;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get packet channel
|
||||||
|
* @return PacketChannel
|
||||||
|
*/
|
||||||
|
public String getChannel() {
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get payload data
|
||||||
|
* @return AbstractPacketPayload
|
||||||
|
*/
|
||||||
|
public AbstractPacketPayload getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.objects;
|
||||||
|
|
||||||
|
public class AbstractPacketPayload { }
|
|
@ -0,0 +1,20 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.objects;
|
||||||
|
|
||||||
|
public abstract class PayloadHandler<E> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle incoming packet
|
||||||
|
* @param packet AbstractPacket
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked cast")
|
||||||
|
public void handle(AbstractPacket packet) {
|
||||||
|
onReceive((E) packet.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when receiving payload
|
||||||
|
* @param payload Class<E>
|
||||||
|
*/
|
||||||
|
public abstract void onReceive(E payload);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.payloads;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacketPayload;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ClientConnectPayload extends AbstractPacketPayload {
|
||||||
|
|
||||||
|
private UUID uuid;
|
||||||
|
private String token;
|
||||||
|
private String attraction_id;
|
||||||
|
|
||||||
|
public UUID getUUID() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttractionID() {
|
||||||
|
return attraction_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.payloads;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacketPayload;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ClientDisconnectPayload extends AbstractPacketPayload {
|
||||||
|
|
||||||
|
private UUID uuid;
|
||||||
|
|
||||||
|
public UUID getUUID() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.packet.payloads.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.packet.objects.AbstractPacketPayload;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ClientOperatorClickPayload extends AbstractPacketPayload {
|
||||||
|
|
||||||
|
private UUID uuid;
|
||||||
|
private String item_id;
|
||||||
|
|
||||||
|
public UUID getUUID() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getItemID() {
|
||||||
|
return item_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.player;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.ThemeParkConnectorAPI;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.states.IdleState;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
public class PlayerStateService {
|
||||||
|
|
||||||
|
private int TaskID = 0;
|
||||||
|
private int strike = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to start pushing player state data
|
||||||
|
*/
|
||||||
|
public void start() {
|
||||||
|
if(TaskID != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Check if shutting down
|
||||||
|
if(ThemeParkConnector.getInstance().isDisabling())
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Start pushing data asynchronously
|
||||||
|
strike = -1;
|
||||||
|
AtomicLong stamp = new AtomicLong(System.currentTimeMillis());
|
||||||
|
ThemeParkConnectorAPI api = ThemeParkConnector.getInstance().getAPI();
|
||||||
|
TaskID = Bukkit.getScheduler().runTaskTimerAsynchronously(ThemeParkConnector.getInstance(), () -> {
|
||||||
|
int connected = 0;
|
||||||
|
for(ClientConnection client : api.getNetworkingService().getClients())
|
||||||
|
if(client.isConnected())
|
||||||
|
connected++;
|
||||||
|
|
||||||
|
//If no players connected add strike
|
||||||
|
if(connected != 0) {
|
||||||
|
strike = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strike++;
|
||||||
|
if(strike > 2) {
|
||||||
|
api.getNetworkingService().stop();
|
||||||
|
api.getStateService().setState(new IdleState("No users online, closed connection"));
|
||||||
|
}
|
||||||
|
}, 0, 10 * 20).getTaskId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop pushing player state data
|
||||||
|
*/
|
||||||
|
public void stop() {
|
||||||
|
if(TaskID == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Bukkit.getScheduler().cancelTask(TaskID);
|
||||||
|
TaskID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.show;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||||
|
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||||
|
import nl.iobyte.menuapi.item.ItemBuilder;
|
||||||
|
import nl.iobyte.themepark.ThemePark;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.show.objects.Ticket;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class ShowService {
|
||||||
|
|
||||||
|
private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
|
|
||||||
|
public String redeemTicket(UUID uuid, String voucher) {
|
||||||
|
if(ThemeParkConnector.getInstance().getEconomy() == null)
|
||||||
|
return "No economy manager found";
|
||||||
|
|
||||||
|
if(uuid == null || voucher == null)
|
||||||
|
return "Invalid parameters";
|
||||||
|
|
||||||
|
try {
|
||||||
|
ArrayList<Map<String, Object>> resultSet = ThemePark.getInstance().getAPI().getDatabaseService().executeQuery(
|
||||||
|
"remote",
|
||||||
|
"SELECT `shows`.id, `shows`.title, seats.seat, seats.date, `shows`.vault_price, paid FROM seats INNER JOIN `shows` ON `shows`.id=seats.show_id WHERE uuid=? AND voucher=? AND loaded=0 LIMIT 1",
|
||||||
|
new HashMap<>(){{
|
||||||
|
put(1, uuid.toString().replace("-", ""));
|
||||||
|
put(2, voucher);
|
||||||
|
}}
|
||||||
|
);
|
||||||
|
|
||||||
|
if(resultSet == null)
|
||||||
|
return "Database error";
|
||||||
|
|
||||||
|
if(resultSet.isEmpty())
|
||||||
|
return "No results";
|
||||||
|
|
||||||
|
String id = "";
|
||||||
|
String name = "";
|
||||||
|
int seat = 0;
|
||||||
|
Date date = new Date();
|
||||||
|
Ticket ticket = new Ticket(voucher, id, seat, date, uuid);
|
||||||
|
for(Map<String, Object> map : resultSet) {
|
||||||
|
id = map.get("id").toString();
|
||||||
|
double price = Double.parseDouble((String) map.get("vault_price"));
|
||||||
|
if(!((boolean) map.get("paid"))) {
|
||||||
|
if (!ThemeParkConnector.getInstance().getEconomy().withdrawPlayer(Bukkit.getOfflinePlayer(uuid), price).transactionSuccess()) {
|
||||||
|
String finalId = id;
|
||||||
|
ThemePark.getInstance().getAPI().getDatabaseService().execute(
|
||||||
|
"remote",
|
||||||
|
"DELETE FROM seats WHERE uuid=? AND voucher=? AND show_id=?",
|
||||||
|
new HashMap<>(){{
|
||||||
|
put(1, uuid.toString().replace("-", ""));
|
||||||
|
put(2, voucher);
|
||||||
|
put(3, finalId);
|
||||||
|
}}
|
||||||
|
);
|
||||||
|
return "Not enough money";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
name = (String) map.get("title");
|
||||||
|
seat = (int) map.get("seat");
|
||||||
|
date = (Timestamp) map.get("date");
|
||||||
|
ticket = new Ticket(voucher, id, seat, date, uuid);
|
||||||
|
String finalId = id;
|
||||||
|
ThemePark.getInstance().getAPI().getDatabaseService().execute(
|
||||||
|
"remote",
|
||||||
|
"UPDATE seats SET paid=1 WHERE uuid=? AND voucher=? AND show_id=?",
|
||||||
|
new HashMap<>(){{
|
||||||
|
put(1, uuid.toString().replace("-", ""));
|
||||||
|
put(2, voucher);
|
||||||
|
put(3, finalId);
|
||||||
|
}}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemBuilder builder = new ItemBuilder(Material.PAPER);
|
||||||
|
builder.setName("&f" + name);
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
list.add("&6Seat: &f" + ticket.getSeat());
|
||||||
|
list.add("&6Date: &f" +format.format(ticket.getShowDate()));
|
||||||
|
builder.setLore(list);
|
||||||
|
|
||||||
|
Gson g = new Gson();
|
||||||
|
NBTItem item = new NBTItem(builder.getItem());
|
||||||
|
NBTCompound compound = item.addCompound("data");
|
||||||
|
compound.setString("ticket", g.toJson(ticket, Ticket.class));
|
||||||
|
|
||||||
|
Player player = Bukkit.getPlayer(uuid);
|
||||||
|
player.getInventory().addItem(item.getItem());
|
||||||
|
return "true";
|
||||||
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Something went wrong";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setValid(Ticket ticket) {
|
||||||
|
if(ticket == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
int i = ThemePark.getInstance().getAPI().getDatabaseService().executeUpdate(
|
||||||
|
"remote",
|
||||||
|
"UPDATE seats SET loaded=1 WHERE uuid=? AND voucher=? AND show_id=?",
|
||||||
|
new HashMap<>(){{
|
||||||
|
put(1, ticket.getUUID().toString().replace("-", ""));
|
||||||
|
put(2, ticket.getID());
|
||||||
|
put(3, ticket.getShowID());
|
||||||
|
}}
|
||||||
|
);
|
||||||
|
|
||||||
|
if(i > 0)
|
||||||
|
return true;
|
||||||
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.show.objects;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class Ticket {
|
||||||
|
|
||||||
|
private final String show, id;
|
||||||
|
private final int seat;
|
||||||
|
private final Date date;
|
||||||
|
private final UUID uuid;
|
||||||
|
|
||||||
|
public Ticket(String id, String show, int seat, Date date, UUID uuid) {
|
||||||
|
this.id = id;
|
||||||
|
this.show = show;
|
||||||
|
this.seat = seat;
|
||||||
|
this.date = date;
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getShowID() {
|
||||||
|
return show;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSeat() {
|
||||||
|
return seat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getShowDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUUID() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.state;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.objects.AbstractState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.states.ConnectedState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.states.ConnectingState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.states.IdleState;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
public class StateService {
|
||||||
|
|
||||||
|
private AbstractState currentState = new IdleState();
|
||||||
|
private final List<BiConsumer<AbstractState, AbstractState>> listeners = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register listener for State changes
|
||||||
|
* @param listener BiConsumer<AbstractState, AbstractState>
|
||||||
|
*/
|
||||||
|
public void addListener(BiConsumer<AbstractState, AbstractState> listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current state
|
||||||
|
* @return AbstractState
|
||||||
|
*/
|
||||||
|
public AbstractState getCurrentState() {
|
||||||
|
return currentState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnecting() {
|
||||||
|
return currentState instanceof ConnectingState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return currentState instanceof ConnectedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set current state
|
||||||
|
* @param currentState AbstractState
|
||||||
|
*/
|
||||||
|
public void setState(AbstractState currentState) {
|
||||||
|
AbstractState oldState = this.currentState;
|
||||||
|
this.currentState = currentState;
|
||||||
|
for(BiConsumer<AbstractState, AbstractState> listener : listeners)
|
||||||
|
listener.accept(oldState, currentState);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.state.objects;
|
||||||
|
|
||||||
|
public class AbstractState {
|
||||||
|
|
||||||
|
private final String name, description;
|
||||||
|
private final boolean canConnect, clientConnect;
|
||||||
|
|
||||||
|
public AbstractState(String name, String description, boolean canConnect, boolean clientConnect) {
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.canConnect = canConnect;
|
||||||
|
this.clientConnect = clientConnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get state name
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getType() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get description of state
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get if server can connect
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean canConnect() {
|
||||||
|
return canConnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get if client can connect
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean canClientConnect() {
|
||||||
|
return clientConnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.state.states;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.objects.AbstractState;
|
||||||
|
|
||||||
|
public class ConnectedState extends AbstractState {
|
||||||
|
|
||||||
|
public ConnectedState() {
|
||||||
|
super("Connected", "Connected to ThemeParkConnector network", false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.state.states;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.objects.AbstractState;
|
||||||
|
|
||||||
|
public class ConnectingState extends AbstractState {
|
||||||
|
|
||||||
|
public ConnectingState() {
|
||||||
|
super("Connecting", "Attempting to connect to ThemeParkConnector network", false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package nl.iobyte.themeparkconnector.api.state.states;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.objects.AbstractState;
|
||||||
|
|
||||||
|
public class IdleState extends AbstractState {
|
||||||
|
|
||||||
|
public IdleState() {
|
||||||
|
this("Nothing going on");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdleState(String description) {
|
||||||
|
super("Idle", description, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package nl.iobyte.themeparkconnector.commands;
|
||||||
|
|
||||||
|
import nl.iobyte.commandapi.CommandFactory;
|
||||||
|
import nl.iobyte.commandapi.middlewares.PermissionMiddleware;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.commands.subcommands.*;
|
||||||
|
import nl.iobyte.themeparkconnector.commands.subcommands.operator.OperatorCommands;
|
||||||
|
|
||||||
|
public class ThemeParkConnectorCommand {
|
||||||
|
|
||||||
|
//Load command data
|
||||||
|
public ThemeParkConnectorCommand() {
|
||||||
|
CommandFactory factory = new CommandFactory("themeparkconnector");
|
||||||
|
factory.addSubCommand(new HelpCommand(factory))
|
||||||
|
.addSubCommand(new ConnectCommand());
|
||||||
|
|
||||||
|
//Admin
|
||||||
|
factory.addSubCommand(new StatusCommand())
|
||||||
|
.addSubCommand(new NotificationCommand())
|
||||||
|
.addSubCommand(new DisconnectCommand());
|
||||||
|
|
||||||
|
//Operator
|
||||||
|
OperatorCommands.load(factory);
|
||||||
|
|
||||||
|
//Middleware
|
||||||
|
factory.addMiddleware(new PermissionMiddleware());
|
||||||
|
|
||||||
|
//Register command
|
||||||
|
factory.registerCommand(ThemeParkConnector.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package nl.iobyte.themeparkconnector.commands.arguments;
|
||||||
|
|
||||||
|
import nl.iobyte.commandapi.interfaces.ICommandArgument;
|
||||||
|
import nl.iobyte.commandapi.objects.ArgumentCheck;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItem;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItemState;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class OperatorArgument implements ICommandArgument<OperatorItemState> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message to display when giving an error
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getMessage(String[] args) {
|
||||||
|
return "Incorrect operator information: "+ ChatColor.WHITE +
|
||||||
|
String.join(
|
||||||
|
",",
|
||||||
|
Arrays.asList(args).subList(0, Math.min(args.length, 3))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if argument is valid OperatorItemState
|
||||||
|
* @param sender CommandSender
|
||||||
|
* @param args Arguments passed by Command
|
||||||
|
* @param previousArguments Previous arguments
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public ArgumentCheck checkArgument(CommandSender sender, String[] args, List<Object> previousArguments) {
|
||||||
|
if(args.length < 3)
|
||||||
|
return new ArgumentCheck(false, 1);
|
||||||
|
|
||||||
|
AttractionOperator operator = ThemeParkConnector.getInstance().getAPI().getOperatorService().getOperator(args[0]);
|
||||||
|
if(operator == null)
|
||||||
|
return new ArgumentCheck(false, 1);
|
||||||
|
|
||||||
|
OperatorItem item = operator.getPanel().getItem(args[1]);
|
||||||
|
if(item == null)
|
||||||
|
return new ArgumentCheck(false, 1);
|
||||||
|
|
||||||
|
return new ArgumentCheck(item.hasState(args[2]), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get OperatorItemState passed by command
|
||||||
|
* @param sender CommandSender
|
||||||
|
* @param args Arguments passed by Command
|
||||||
|
* @param previousArguments Previous arguments
|
||||||
|
* @return OperatorItemState
|
||||||
|
*/
|
||||||
|
public OperatorItemState getArgument(CommandSender sender, String[] args, List<Object> previousArguments) {
|
||||||
|
AttractionOperator operator = ThemeParkConnector.getInstance().getAPI().getOperatorService().getOperator(args[0]);
|
||||||
|
previousArguments.add(operator);
|
||||||
|
|
||||||
|
OperatorItem item = operator.getPanel().getItem(args[1]);
|
||||||
|
previousArguments.add(item);
|
||||||
|
|
||||||
|
return item.getState(args[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package nl.iobyte.themeparkconnector.commands.subcommands;
|
||||||
|
|
||||||
|
import nl.iobyte.commandapi.interfaces.SubCommand;
|
||||||
|
import nl.iobyte.themepark.api.attraction.objects.Attraction;
|
||||||
|
import nl.iobyte.themepark.commands.arguments.AttractionArgument;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.Text;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ConnectCommand extends SubCommand {
|
||||||
|
|
||||||
|
public ConnectCommand() {
|
||||||
|
super(new String[]{"connect"});
|
||||||
|
|
||||||
|
addSyntax("/themeparkconnector connect <attraction>")
|
||||||
|
.addArgument(new AttractionArgument())
|
||||||
|
.setAllowConsole(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Attempt to generate an url for the Player
|
||||||
|
public void onPlayerCommand(Player player, List<Object> list, int i) {
|
||||||
|
Attraction attraction = (Attraction) list.get(0);
|
||||||
|
AttractionOperator operator = ThemeParkConnector.getInstance().getAPI().getOperatorService().getOperator(attraction.getID());
|
||||||
|
if(operator == null) {
|
||||||
|
player.sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &4There is no operator for this attraction"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientConnection client = ThemeParkConnector.getInstance().getAPI().getNetworkingService().getClient(
|
||||||
|
player.getUniqueId()
|
||||||
|
);
|
||||||
|
if(!operator.canClientConnect(client)) {
|
||||||
|
player.sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &4You can't connect to the operator of this attraction"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.publishURL(attraction.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onConsoleCommand(CommandSender commandSender, List<Object> list, int i) { }
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package nl.iobyte.themeparkconnector.commands.subcommands;
|
||||||
|
|
||||||
|
import nl.iobyte.commandapi.interfaces.SubCommand;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.ThemeParkConnectorAPI;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.Text;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DisconnectCommand extends SubCommand {
|
||||||
|
|
||||||
|
public DisconnectCommand() {
|
||||||
|
super("themeparkconnector.admin", "disconnect");
|
||||||
|
|
||||||
|
addSyntax("/themeparkconnector disconnect");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Attempt to generate an url for the Player
|
||||||
|
public void onPlayerCommand(Player player, List<Object> list, int i) {
|
||||||
|
onConsoleCommand(player, list, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onConsoleCommand(CommandSender sender, List<Object> list, int i) {
|
||||||
|
ThemeParkConnectorAPI api = ThemeParkConnector.getInstance().getAPI();
|
||||||
|
try {
|
||||||
|
if (api.getStateService().isConnected())
|
||||||
|
api.getNetworkingService().stop();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
sender.sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &4Something went wrong while closing connection"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &aConnection has been closed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package nl.iobyte.themeparkconnector.commands.subcommands;
|
||||||
|
|
||||||
|
import nl.iobyte.commandapi.CommandFactory;
|
||||||
|
import nl.iobyte.commandapi.arguments.number.IntegerArgument;
|
||||||
|
import nl.iobyte.commandapi.interfaces.SubCommand;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.Text;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HelpCommand extends SubCommand {
|
||||||
|
|
||||||
|
private final CommandFactory factory;
|
||||||
|
|
||||||
|
public HelpCommand(CommandFactory factory) {
|
||||||
|
super(new String[]{"help"});
|
||||||
|
|
||||||
|
this.factory = factory;
|
||||||
|
addSyntax("/themeparkconnector help");
|
||||||
|
addSyntax("/themeparkconnector help <page>")
|
||||||
|
.addArgument(new IntegerArgument());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerCommand(Player player, List<Object> list, int i) {
|
||||||
|
onConsoleCommand(player, list, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send CommandSender list of commands it has access to
|
||||||
|
public void onConsoleCommand(CommandSender sender, List<Object> list, int i) {
|
||||||
|
List<SubCommand> commands = factory.getApplicableSubCommands(sender);
|
||||||
|
if(commands.size() <= 5) {
|
||||||
|
sendSinglePage(sender, commands);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMultiPage(sender, commands, list, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendSinglePage(CommandSender sender, List<SubCommand> commands) {
|
||||||
|
sender.sendMessage(Text.color("&f&l>==== &6&lThemeParkConnector &l&f====<"));
|
||||||
|
for (SubCommand command : commands)
|
||||||
|
sender.sendMessage(Text.color("&f" + command.getApplicableSyntaxList(sender).get(0).getUsage()));
|
||||||
|
|
||||||
|
sender.sendMessage(Text.color("&f&l>==== &6&lThemeParkConnector &l&f====<"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendMultiPage(CommandSender sender, List<SubCommand> commands, List<Object> list, int i) {
|
||||||
|
int page = 1;
|
||||||
|
int pages = (int) Math.ceil(((double) commands.size()) / 5);
|
||||||
|
if(i == 1)
|
||||||
|
page = (Integer) list.get(0);
|
||||||
|
|
||||||
|
if(page < 1 || page > pages) {
|
||||||
|
sender.sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ Page &6"+page+" &fdoesn't exist"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
page--;
|
||||||
|
int start = page * 5;
|
||||||
|
int end = page * 5 + 5;
|
||||||
|
if(end > commands.size())
|
||||||
|
end = commands.size();
|
||||||
|
|
||||||
|
sender.sendMessage(Text.color("&f&l>==== &6&lThemeParkConnector &f(&6"+(page + 1)+"&f/&6"+pages+"&f) &l&f====<"));
|
||||||
|
for(i = start; i < end; i++)
|
||||||
|
sender.sendMessage(Text.color("&f" + commands.get(i).getApplicableSyntaxList(sender).get(0).getUsage()));
|
||||||
|
|
||||||
|
sender.sendMessage(Text.color("&f&l>==== &6&lThemeParkConnector &l&f====<"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package nl.iobyte.themeparkconnector.commands.subcommands;
|
||||||
|
|
||||||
|
import nl.iobyte.commandapi.arguments.MessageArgument;
|
||||||
|
import nl.iobyte.commandapi.arguments.PlayersArgument;
|
||||||
|
import nl.iobyte.commandapi.interfaces.SubCommand;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.Text;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.objects.Notification;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NotificationCommand extends SubCommand {
|
||||||
|
|
||||||
|
public NotificationCommand() {
|
||||||
|
super("themeparkconnector.admin", "notification");
|
||||||
|
|
||||||
|
addSyntax("/themeparkconnector notification <player> <title> <message>")
|
||||||
|
.addArgument(new PlayersArgument())
|
||||||
|
.addArgument(new MessageArgument())
|
||||||
|
.addArgument(new MessageArgument());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerCommand(Player player, List<Object> objects, int i) {
|
||||||
|
onConsoleCommand(player, objects, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get Notification data and send to Player(s)
|
||||||
|
public void onConsoleCommand(CommandSender sender, List<Object> objects, int i) {
|
||||||
|
Notification notification = new Notification((String) objects.get(1), (String) objects.get(2));
|
||||||
|
for(Player player : (List<Player>) objects.get(0)) {
|
||||||
|
ClientConnection client = ThemeParkConnector.getInstance().getAPI().getNetworkingService().getClient(player.getUniqueId());
|
||||||
|
if(!client.isConnected())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
notification.send(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ The notification has been send to &6"+i+" &fclients"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package nl.iobyte.themeparkconnector.commands.subcommands;
|
||||||
|
|
||||||
|
import nl.iobyte.commandapi.interfaces.SubCommand;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.ThemeParkConnectorAPI;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.state.objects.AbstractState;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.Text;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class StatusCommand extends SubCommand {
|
||||||
|
|
||||||
|
public StatusCommand() {
|
||||||
|
super("themeparkconnector.admin", "status");
|
||||||
|
|
||||||
|
addSyntax("/themeparkconnector status");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerCommand(Player player, List<Object> objects, int i) {
|
||||||
|
onConsoleCommand(player, objects, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Give CommandSender overview of Plugin status
|
||||||
|
public void onConsoleCommand(CommandSender sender, List<Object> objects, int i) {
|
||||||
|
ThemeParkConnectorAPI api = ThemeParkConnector.getInstance().getAPI();
|
||||||
|
AbstractState state = api.getStateService().getCurrentState();
|
||||||
|
|
||||||
|
sender.sendMessage(Text.color("&f&l>==== &6&lThemeParkConnector &l&f====<"));
|
||||||
|
sender.sendMessage(Text.color("&6State: &f"+state.getType()));
|
||||||
|
sender.sendMessage(Text.color("&6Clients: &f"+getClientCount()+"&6/&f"+ Bukkit.getOnlinePlayers().size()));
|
||||||
|
sender.sendMessage(Text.color("&6Description:"));
|
||||||
|
sender.sendMessage(Text.color("&f"+state.getDescription()));
|
||||||
|
sender.sendMessage(Text.color("&f&l>==== &6&lThemeParkConnector &l&f====<"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get clients connected to ThemeParkConnector
|
||||||
|
private String getClientCount() {
|
||||||
|
int i = 0;
|
||||||
|
for(ClientConnection client : ThemeParkConnector.getInstance().getAPI().getNetworkingService().getClients())
|
||||||
|
if(client.isConnected())
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return Integer.toString(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package nl.iobyte.themeparkconnector.commands.subcommands.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.commandapi.CommandFactory;
|
||||||
|
|
||||||
|
public class OperatorCommands {
|
||||||
|
|
||||||
|
public static void load(CommandFactory factory) {
|
||||||
|
factory.addSubCommand(new OperatorReloadCommand())
|
||||||
|
.addSubCommand(new OperatorStateCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package nl.iobyte.themeparkconnector.commands.subcommands.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.commandapi.interfaces.SubCommand;
|
||||||
|
import nl.iobyte.themeparkconnector.api.load.objects.OperatorDataLoader;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.Text;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class OperatorReloadCommand extends SubCommand {
|
||||||
|
|
||||||
|
public OperatorReloadCommand() {
|
||||||
|
super("themeparkconnector.admin", "operator", "reload");
|
||||||
|
|
||||||
|
addSyntax("/themeparkconnector operator reload");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerCommand(Player player, List<Object> list, int i) {
|
||||||
|
onConsoleCommand(player, list, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConsoleCommand(CommandSender sender, List<Object> list, int i) {
|
||||||
|
sender.sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &6Attempting to load ride operators"));
|
||||||
|
new OperatorDataLoader().load();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package nl.iobyte.themeparkconnector.commands.subcommands.operator;
|
||||||
|
|
||||||
|
import nl.iobyte.commandapi.arguments.StringArgument;
|
||||||
|
import nl.iobyte.commandapi.interfaces.SubCommand;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.operator.OperatorStateEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.Text;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItem;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.panel.OperatorItemState;
|
||||||
|
import nl.iobyte.themeparkconnector.commands.arguments.OperatorArgument;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class OperatorStateCommand extends SubCommand {
|
||||||
|
|
||||||
|
public OperatorStateCommand() {
|
||||||
|
super("themeparkconnector.admin", "operator", "state");
|
||||||
|
|
||||||
|
addSyntax("/themeparkconnector operator state <attraction> <item> <state>")
|
||||||
|
.addArgument(new OperatorArgument());
|
||||||
|
|
||||||
|
addSyntax("/themeparkconnector operator state <attraction> <item> <state> <data>")
|
||||||
|
.addArgument(new OperatorArgument())
|
||||||
|
.addArgument(new StringArgument());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerCommand(Player player, List<Object> list, int i) {
|
||||||
|
onConsoleCommand(player, list, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConsoleCommand(CommandSender sender, List<Object> list, int i) {
|
||||||
|
AttractionOperator operator = (AttractionOperator) list.get(0);
|
||||||
|
OperatorItem item = (OperatorItem) list.get(1);
|
||||||
|
OperatorItemState state = (OperatorItemState) list.get(2);
|
||||||
|
OperatorItemState old = item.getActiveState();
|
||||||
|
if(state.getID().equals(old.getID())) {
|
||||||
|
if(sender instanceof Player)
|
||||||
|
sender.sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &4Item already in state: &f"+state.getID()));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.setActiveState(state.getID());
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getEventDispatcher().call(new OperatorStateEvent(
|
||||||
|
operator,
|
||||||
|
item,
|
||||||
|
old,
|
||||||
|
state,
|
||||||
|
i == 0 ? "" : (String) list.get(3)
|
||||||
|
));
|
||||||
|
|
||||||
|
if(sender instanceof Player)
|
||||||
|
sender.sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &aSuccessfully changed state of item to: &f"+state.getID()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package nl.iobyte.themeparkconnector.listeners;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.api.event.attraction.AttractionStatusChangeEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.client.ClientConnection;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.packet.operator.StatusChangePacket;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
|
public class AttractionListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onChange(AttractionStatusChangeEvent e) {
|
||||||
|
AttractionOperator operator = ThemeParkConnector.getInstance().getAPI().getOperatorService().getOperator(e.getAttraction().getID());
|
||||||
|
if(operator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ClientConnection client = operator.getClientConnection();
|
||||||
|
if(client == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Packet
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getNetworkingService().send(
|
||||||
|
client,
|
||||||
|
new StatusChangePacket(
|
||||||
|
e.getCurrent()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package nl.iobyte.themeparkconnector.listeners;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.operator.OperatorConnectEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.operator.OperatorDisconnectEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.operator.OperatorStateEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.network.packet.operator.OperatorStatePacket;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
|
public class OperatorListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onConnect(OperatorConnectEvent e) {
|
||||||
|
String command = e.getOperator().getStartCommand();
|
||||||
|
if(command == null || command.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onState(OperatorStateEvent e) {
|
||||||
|
//Change Packet
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getNetworkingService().send(
|
||||||
|
e.getOperator().getClientConnection(),
|
||||||
|
new OperatorStatePacket(
|
||||||
|
e.getItem().getID(),
|
||||||
|
e.getCurrent(),
|
||||||
|
e.getData()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onDisconnect(OperatorDisconnectEvent e) {
|
||||||
|
String command = e.getOperator().getStopCommand();
|
||||||
|
if(command == null || command.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package nl.iobyte.themeparkconnector.listeners;
|
||||||
|
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.ThemeParkConnectorAPI;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PlayerListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(PlayerJoinEvent e) {
|
||||||
|
Player player = e.getPlayer();
|
||||||
|
ThemeParkConnectorAPI api = ThemeParkConnector.getInstance().getAPI();
|
||||||
|
|
||||||
|
//Register ClientConnection
|
||||||
|
api.getNetworkingService().register(player);
|
||||||
|
}
|
||||||
|
@EventHandler
|
||||||
|
public void onQuit(PlayerQuitEvent e) {
|
||||||
|
Player player = e.getPlayer();
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
|
||||||
|
//Remove ClientConnection
|
||||||
|
ThemeParkConnector.getInstance().getAPI().getNetworkingService().remove(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package nl.iobyte.themeparkconnector.listeners;
|
||||||
|
|
||||||
|
import nl.iobyte.themepark.ThemePark;
|
||||||
|
import nl.iobyte.themepark.api.event.ridecount.RideCountAddEvent;
|
||||||
|
import nl.iobyte.themepark.api.ridecount.objects.RideCount;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class RideCountListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onAdd(RideCountAddEvent e) {
|
||||||
|
RideCount rc = e.getRideCount();
|
||||||
|
ThemePark.getInstance().getAPI().getDatabaseService().executeAsync(
|
||||||
|
"remote",
|
||||||
|
"INSERT INTO ridecounts(uuid, attraction_id, year, month, week, day, count) VALUES (?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE count=?",
|
||||||
|
new HashMap<>() {{
|
||||||
|
put(1, rc.getUUID().toString());
|
||||||
|
put(2, rc.getAttractionID());
|
||||||
|
put(3, rc.getYear());
|
||||||
|
put(4, rc.getMonth());
|
||||||
|
put(5, rc.getWeek());
|
||||||
|
put(6, rc.getDay());
|
||||||
|
put(7, rc.getCount());
|
||||||
|
put(8, rc.getCount());
|
||||||
|
}}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package nl.iobyte.themeparkconnector.listeners;
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.ClickEvent;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
import nl.iobyte.themepark.ThemePark;
|
||||||
|
import nl.iobyte.themepark.api.attraction.objects.Attraction;
|
||||||
|
import nl.iobyte.themepark.api.message.MessageKey;
|
||||||
|
import nl.iobyte.themepark.utils.LocationUtil;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.config.enums.StorageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.Text;
|
||||||
|
import nl.iobyte.themeparkconnector.api.operator.objects.AttractionOperator;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.Sign;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.block.SignChangeEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
|
||||||
|
public class RideOperatorListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlace(SignChangeEvent e) {
|
||||||
|
if(e.getLines().length < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!e.getLine(0).equalsIgnoreCase(ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getString(StorageKey.SIGN_CONTROL_NAME)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
String id = e.getLine(1);
|
||||||
|
if(!ThemePark.getInstance().getAPI().getAttractionService().hasAttraction(id)) {
|
||||||
|
e.getPlayer().sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &4There is no attraction with ID: &f"+id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ThemeParkConnector.getInstance().getAPI().getOperatorService().hasOperator(id)) {
|
||||||
|
e.getPlayer().sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &4There is no operator for this attraction"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.setLine(0, Text.color(ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getString(StorageKey.SIGN_CONTROL_TITLE)));
|
||||||
|
e.getPlayer().sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &aSuccessfully made an operator sign"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onClick(PlayerInteractEvent e) {
|
||||||
|
if(e.getAction() == Action.LEFT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_AIR)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(e.getClickedBlock() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block block = e.getClickedBlock();
|
||||||
|
if(!(block.getState() instanceof Sign))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Sign sign = (Sign) block.getState();
|
||||||
|
if(!ChatColor.stripColor(sign.getLine(0)).equals(Text.color(ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getString(StorageKey.SIGN_CONTROL_TITLE))))
|
||||||
|
return;
|
||||||
|
|
||||||
|
String id = ChatColor.stripColor(sign.getLine(1));
|
||||||
|
if(id == null || id.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Player player = e.getPlayer();
|
||||||
|
if(!ThemePark.getInstance().getAPI().getAttractionService().hasAttraction(id)) {
|
||||||
|
player.sendMessage(Text.color("&6&lThemeParkConnectorMC &f➢ &4No attraction with ID: &f"+id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bukkit.dispatchCommand(player, "/tpc connect "+id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,180 @@
|
||||||
|
package nl.iobyte.themeparkconnector.listeners;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||||
|
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||||
|
import nl.iobyte.themepark.utils.LocationUtil;
|
||||||
|
import nl.iobyte.themeparkconnector.ThemeParkConnector;
|
||||||
|
import nl.iobyte.themeparkconnector.api.config.enums.StorageKey;
|
||||||
|
import nl.iobyte.themeparkconnector.api.event.ticket.TicketScanEvent;
|
||||||
|
import nl.iobyte.themeparkconnector.api.message.Text;
|
||||||
|
import nl.iobyte.themeparkconnector.api.show.objects.Ticket;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.Sign;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.block.SignChangeEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class TicketListener implements Listener {
|
||||||
|
|
||||||
|
private final SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlace(SignChangeEvent e) {
|
||||||
|
if(e.getLines().length < 4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!e.getLine(0).equalsIgnoreCase(ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getString(StorageKey.SIGN_SCAN_NAME)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Player player = e.getPlayer();
|
||||||
|
if(e.getLine(1) == null || e.getLine(1).isEmpty()) {
|
||||||
|
player.sendMessage(Text.color("&4Can't make a TicketScanner with empty show ID."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e.getLine(2) == null || e.getLine(2).isEmpty()) {
|
||||||
|
player.sendMessage(Text.color("&4Can't make a TicketScanner with empty show Date."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String date = e.getLine(2);
|
||||||
|
if(isValidFormat("HH:mm", date) && isValidFormat("HH:mm dd-MM-yyyy", date)) {
|
||||||
|
player.sendMessage(Text.color("&4Can't make a TicketScanner with incorrect date, example: 20:00 or 20:00 04-04-2019"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e.getLine(3) == null || e.getLine(3).isEmpty()) {
|
||||||
|
player.sendMessage(Text.color("&4Can't make a TicketScanner with empty teleport location."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String world = player.getLocation().getWorld().getName();
|
||||||
|
if(LocationUtil.fromString(world + ":" + e.getLine(3)) == null) {
|
||||||
|
player.sendMessage(Text.color("&4Can't make a TicketScanner with incorrect teleport location."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.setLine(0, Text.color(ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getString(StorageKey.SIGN_SCAN_TITLE)));
|
||||||
|
player.sendMessage(Text.color("&aSuccessfully made a TicketScanner"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onScan(PlayerInteractEvent e) {
|
||||||
|
if(e.getAction() == Action.LEFT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_AIR)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(e.getClickedBlock() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Block block = e.getClickedBlock();
|
||||||
|
if(!(block.getState() instanceof Sign))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Sign sign = (Sign) block.getState();
|
||||||
|
if(!sign.getLine(0).equals(Text.color(ThemeParkConnector.getInstance().getAPI().getConfigurationManager().getString(StorageKey.SIGN_SCAN_TITLE)))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String id = ChatColor.stripColor(sign.getLine(1));
|
||||||
|
if(id == null || id.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
String date = ChatColor.stripColor(sign.getLine(2));
|
||||||
|
if(date == null || date.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(isValidFormat("HH:mm", date) && isValidFormat("HH:mm dd-MM-yyyy", date)) {
|
||||||
|
System.out.println("Invalid date format");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isValidFormat("HH:mm dd-MM-yyyy", date))
|
||||||
|
date = date + " " + format.format(new Date());
|
||||||
|
|
||||||
|
Location location = LocationUtil.fromString(sign.getLocation().getWorld().getName() + ":" + sign.getLine(3));
|
||||||
|
if(location == null) {
|
||||||
|
System.out.println("Invalid Location");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e.getItem() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ItemStack item = e.getItem();
|
||||||
|
if(item.getType() != Material.PAPER)
|
||||||
|
return;
|
||||||
|
|
||||||
|
NBTItem it = new NBTItem(item);
|
||||||
|
if(!it.hasKey("data")) {
|
||||||
|
System.out.println("Missing data key");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NBTCompound compound = it.getCompound("data");
|
||||||
|
if(!compound.hasKey("ticket")) {
|
||||||
|
System.out.println("Missing ticket key");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gson g = new Gson();
|
||||||
|
Ticket ticket = g.fromJson(it.getCompound("data").getString("ticket"), Ticket.class);
|
||||||
|
if(ticket == null) {
|
||||||
|
System.out.println("Couldn't get ticket class using Gson");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!id.equals(ticket.getShowID())) {
|
||||||
|
System.out.println("Different show id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!date.equals(new SimpleDateFormat("HH:mm dd-MM-yyyy").format(ticket.getShowDate()))) {
|
||||||
|
System.out.println("Different date");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player player = e.getPlayer();
|
||||||
|
boolean b = ThemeParkConnector.getInstance().getAPI().getShowService().setValid(ticket);
|
||||||
|
|
||||||
|
TicketScanEvent event = new TicketScanEvent(player.getUniqueId(), ticket, b);
|
||||||
|
Bukkit.getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
int i = player.getInventory().getHeldItemSlot();
|
||||||
|
player.getInventory().remove(player.getInventory().getItem(i));
|
||||||
|
if(!b) {
|
||||||
|
player.sendMessage(Text.color("&4Invalid ticket."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!event.isCancelled())
|
||||||
|
player.teleport(location);
|
||||||
|
|
||||||
|
player.sendMessage(Text.color("&6Used ticket for Show: " + item.getItemMeta().getDisplayName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isValidFormat(String format, String value) {
|
||||||
|
try {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat(format);
|
||||||
|
Date date = sdf.parse(value);
|
||||||
|
if(!value.equals(sdf.format(date)))
|
||||||
|
date = null;
|
||||||
|
|
||||||
|
return date == null;
|
||||||
|
} catch(ParseException ex) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package nl.iobyte.themeparkconnector.logger;
|
||||||
|
|
||||||
|
public class ThemeParkConnectorLogger {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print message to the console
|
||||||
|
* @param msg Message string
|
||||||
|
*/
|
||||||
|
public static void toConsole(String msg) {
|
||||||
|
System.out.println("[ThemeParkConnector] "+msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
302
src/main/java/nl/iobyte/themeparkconnector/sbd/License.java
Normal file
302
src/main/java/nl/iobyte/themeparkconnector/sbd/License.java
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
package nl.iobyte.themeparkconnector.sbd;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* License class for SBDevelopment
|
||||||
|
*
|
||||||
|
* v1.6 - Changed on 06-08-2020
|
||||||
|
*
|
||||||
|
* @author Stijn [SBDeveloper]
|
||||||
|
* @since 23-12-2019
|
||||||
|
*/
|
||||||
|
public class License implements Listener {
|
||||||
|
/*
|
||||||
|
This file is part of ThemeParkRidecountAddon.
|
||||||
|
Copyright (c) 2018-2020 SBDevelopment - All Rights Reserved
|
||||||
|
Unauthorized copying of this file, via any medium is strictly prohibited
|
||||||
|
Proprietary and confidential
|
||||||
|
Written by Stijn Bannink <stijnbannink23@gmail.com>, January 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
private JavaPlugin plugin; // The plugin instance
|
||||||
|
private String license; // The license code
|
||||||
|
private String prefix; // The correct prefix for this plugin
|
||||||
|
private String invalidReason; // The reason the license is invalid, if null it's not invalid!
|
||||||
|
private static Boolean valid; // If true, it's valid, if false, it's not valid, if null it's not checked!
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new license
|
||||||
|
* @param plugin The Main class [Javaplugin]
|
||||||
|
* @param prefix The prefix, like TPP or AF
|
||||||
|
* @param license The license from the config
|
||||||
|
*/
|
||||||
|
public License(JavaPlugin plugin, String prefix, String license) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.license = license;
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||||
|
|
||||||
|
validateLicense();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(PlayerJoinEvent e) {
|
||||||
|
if (this.invalidReason == null) return;
|
||||||
|
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
if (p.isOp() || p.hasPermission("sbd.licensemessages")) {
|
||||||
|
Bukkit.getScheduler().runTaskLater(this.plugin, () -> p.sendMessage(ChatColor.GOLD + "[" + ChatColor.RED + this.plugin.getName() + ChatColor.GOLD + "] " + ChatColor.RED + "The license is incorrect! Reason: " + ChatColor.GOLD + this.invalidReason), 3 * 20L /* 3 sec */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a license
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void validateLicense() {
|
||||||
|
//STEP 1: Check prefix
|
||||||
|
if (!this.license.split("-")[0].contains(this.prefix)) {
|
||||||
|
disable("You used the wrong license for this product.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//STEP 2: Send license request
|
||||||
|
String url = "https://sbdplugins.nl/wp-json/lmfwc/v2/licenses/" + this.license;
|
||||||
|
JsonObject response;
|
||||||
|
try {
|
||||||
|
response = sendGETRequestJSON(url);
|
||||||
|
} catch (IOException e) {
|
||||||
|
disable("Couldn't send the request.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response == null) {
|
||||||
|
disable("Couldn't send the request.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject dataObject = response.get("data").getAsJsonObject();
|
||||||
|
|
||||||
|
//STEP 3: Check status
|
||||||
|
switch(dataObject.get("status").getAsString()) {
|
||||||
|
case "2":
|
||||||
|
//Delivered -> Try to activate (double check timesActivated)
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
//Activated!
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
disable("Your license has a wrong status.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//STEP 4: Check times activated, and if not activated, activate.
|
||||||
|
if (dataObject.get("timesActivated").isJsonNull() || dataObject.get("timesActivated").getAsString().equalsIgnoreCase("0")) {
|
||||||
|
activate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//STEP 5: Check expire date
|
||||||
|
if (dataObject.get("expiresAt").isJsonNull()) {
|
||||||
|
disable("Your license has no expire date.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
Date date;
|
||||||
|
try {
|
||||||
|
date = format.parse(dataObject.get("expiresAt").getAsString());
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
disable("Your license has a wrong expire date.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (date == null) {
|
||||||
|
disable("Your license has a wrong expire date.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(date.after(new Date()))) {
|
||||||
|
disable("Your license has expired.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//STEP 6: Check IP and port.
|
||||||
|
if (!dataObject.get("ipcheck").getAsBoolean()) {
|
||||||
|
disable("Your license has been used with another IP. Update it in our Discord.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataObject.get("port").isJsonNull()) {
|
||||||
|
disable("Your license has no port.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String por = dataObject.get("port").getAsString();
|
||||||
|
if (!checkPortValue(Bukkit.getServer().getPort(), por)) {
|
||||||
|
disable("Your license has been used with another Port. Update it in our Discord.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activate the license
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void activate() {
|
||||||
|
//STEP 1: Send license activate request
|
||||||
|
String url = "https://sbdplugins.nl/wp-json/lmfwc/v2/licenses/activate/" + this.license + "?port=" + Bukkit.getServer().getPort();
|
||||||
|
|
||||||
|
JsonObject response;
|
||||||
|
try {
|
||||||
|
response = sendGETRequestJSON(url);
|
||||||
|
} catch (IOException e) {
|
||||||
|
disable("Couldn't send the activate request.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response == null) {
|
||||||
|
disable("Couldn't send the activate request.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject dataObject = response.get("data").getAsJsonObject();
|
||||||
|
|
||||||
|
//STEP 2: Check status
|
||||||
|
switch(dataObject.get("status").getAsString()) {
|
||||||
|
case "2":
|
||||||
|
//Delivered -> STILL NOT ACTIVATED?! -> Double check
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
//Activated!
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
disable("Your license has a wrong status.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//STEP 3: Check times activated, and if still not activated, disable.
|
||||||
|
if (dataObject.get("timesActivated").isJsonNull() || dataObject.get("timesActivated").getAsString().equalsIgnoreCase("0")) {
|
||||||
|
disable("Couldn't activate the license.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable the plugin (private)
|
||||||
|
*
|
||||||
|
* @param reason The disabling reason
|
||||||
|
*/
|
||||||
|
private void disable(String reason) {
|
||||||
|
this.invalidReason = reason;
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTask(this.plugin, () -> {
|
||||||
|
valid = false;
|
||||||
|
|
||||||
|
Bukkit.getLogger().severe("[" + this.plugin.getName() + "] Stopping plugin because licensing system check failed.");
|
||||||
|
Bukkit.getLogger().severe("[" + this.plugin.getName() + "] Reason: " + reason);
|
||||||
|
Bukkit.getLogger().severe("[" + this.plugin.getName() + "] Contact the developer if you believe something is wrong on their side.");
|
||||||
|
Bukkit.getPluginManager().disablePlugin(this.plugin);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an GET request with JSONObject response
|
||||||
|
*
|
||||||
|
* @param uri The URL
|
||||||
|
*
|
||||||
|
* @return The JSONObject
|
||||||
|
* @throws IOException URL errors
|
||||||
|
*/
|
||||||
|
private JsonObject sendGETRequestJSON(String uri) throws IOException {
|
||||||
|
URL url = new URL(uri);
|
||||||
|
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||||
|
con.setRequestMethod("GET");
|
||||||
|
con.setRequestProperty("User-Agent", "Mozilla/5.0");
|
||||||
|
String authStringEnc = "Y2tfMGEzNWEzMWE2NzExNmM3NDg2MGEwYTJhNjUxNGVjZjM4NTBmM2JmMDpjc185NmYxZGNlYjI4MWRkZDExOTBjMzQ3ZjJjYzMwMGNjZTIzYWNhODI1";
|
||||||
|
con.setRequestProperty("Authorization", "Basic " + authStringEnc);
|
||||||
|
int code = con.getResponseCode();
|
||||||
|
if (code == 404) {
|
||||||
|
disable("404_error");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||||
|
String inputLine;
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
while ((inputLine = in.readLine()) != null) {
|
||||||
|
response.append(inputLine);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
JsonParser parser = new JsonParser();
|
||||||
|
return parser.parse(response.toString()).getAsJsonObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkPortValue(int input, String dataValue) {
|
||||||
|
//STEP 1: Check wildcard
|
||||||
|
if (dataValue.equals("*")) return true;
|
||||||
|
|
||||||
|
//STEP 2: Check if equals
|
||||||
|
try {
|
||||||
|
int dataVal = Integer.parseInt(dataValue);
|
||||||
|
|
||||||
|
return input == dataVal;
|
||||||
|
} catch (NumberFormatException ignored) {}
|
||||||
|
|
||||||
|
//STEP 3: Check if range
|
||||||
|
if (dataValue.contains("-")) {
|
||||||
|
String[] dataSplit = dataValue.split("-");
|
||||||
|
|
||||||
|
//STEP 3.1: Check if min or max is wildcard
|
||||||
|
if (dataSplit[0].equals("*") && !dataSplit[1].equals("*")) {
|
||||||
|
int max = Integer.parseInt(dataSplit[1]);
|
||||||
|
return input <= max;
|
||||||
|
} else if (dataSplit[1].equals("*") && !dataSplit[0].equals("*")) {
|
||||||
|
int min = Integer.parseInt(dataSplit[0]);
|
||||||
|
return min <= input;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
int min = Integer.parseInt(dataSplit[0]);
|
||||||
|
int max = Integer.parseInt(dataSplit[1]);
|
||||||
|
|
||||||
|
return (min <= input) && (input <= max);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Else, invalid value
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the license is valid
|
||||||
|
*
|
||||||
|
* @return true -> VALID, false -> INVALID, null -> UNCHECKED
|
||||||
|
*/
|
||||||
|
public static boolean isValid() {
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
package nl.iobyte.themeparkconnector.sbd;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update class for SBDevelopment
|
||||||
|
* @author Stijn [SBDeveloper]
|
||||||
|
* @since 18-01-2020
|
||||||
|
* @version 1.2
|
||||||
|
*
|
||||||
|
* © Stijn Bannink <stijnbannink23@gmail.com> - All rights reserved.
|
||||||
|
*/
|
||||||
|
public class UpdateManager {
|
||||||
|
|
||||||
|
private static String SPIGOT_API = "http://api.spiget.org/v2/resources/%d/versions?size=1&sort=-releaseDate";
|
||||||
|
private static String SBDPLUGINS_API = "http://updates.sbdplugins.nl:4000/api/resources/%d";
|
||||||
|
|
||||||
|
private Plugin plugin;
|
||||||
|
private String currentVersion;
|
||||||
|
private int resourceID;
|
||||||
|
private CheckType type;
|
||||||
|
private BiConsumer<VersionResponse, String> versionResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new UpdateManager
|
||||||
|
*
|
||||||
|
* @param plugin The javaplugin (Main class)
|
||||||
|
* @param resourceID The resourceID on spigot/sbdplugins
|
||||||
|
* @param type The check type
|
||||||
|
*/
|
||||||
|
public UpdateManager(Plugin plugin, int resourceID, CheckType type) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.currentVersion = plugin.getDescription().getVersion();
|
||||||
|
this.resourceID = resourceID;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the response given by check();
|
||||||
|
* @param versionResponse The response
|
||||||
|
* @return The updatemanager
|
||||||
|
*/
|
||||||
|
public UpdateManager handleResponse(BiConsumer<VersionResponse, String> versionResponse) {
|
||||||
|
this.versionResponse = versionResponse;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for a new version
|
||||||
|
*/
|
||||||
|
public void check() {
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> {
|
||||||
|
try {
|
||||||
|
HttpURLConnection con = null;
|
||||||
|
if (type == CheckType.SPIGOT) {
|
||||||
|
con = (HttpURLConnection) new URL(String.format(SPIGOT_API, this.resourceID)).openConnection();
|
||||||
|
} else if (type == CheckType.SBDPLUGINS) {
|
||||||
|
con = (HttpURLConnection) new URL(String.format(SBDPLUGINS_API, this.resourceID)).openConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con == null) return;
|
||||||
|
|
||||||
|
con.setRequestMethod("GET");
|
||||||
|
con.setRequestProperty("User-Agent", "Mozilla/5.0");
|
||||||
|
|
||||||
|
String version = null;
|
||||||
|
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||||
|
String inputLine;
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
while ((inputLine = in.readLine()) != null) {
|
||||||
|
response.append(inputLine);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
JsonParser parser = new JsonParser();
|
||||||
|
|
||||||
|
if (type == CheckType.SPIGOT) {
|
||||||
|
JsonArray array = parser.parse(response.toString()).getAsJsonArray();
|
||||||
|
|
||||||
|
version = array.get(0).getAsJsonObject().get("name").getAsString();
|
||||||
|
} else if (type == CheckType.SBDPLUGINS) {
|
||||||
|
JsonObject object = parser.parse(response.toString()).getAsJsonObject();
|
||||||
|
|
||||||
|
version = object.get("data").getAsJsonObject().get("version").getAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version == null) return;
|
||||||
|
|
||||||
|
boolean latestVersion = version.equalsIgnoreCase(this.currentVersion);
|
||||||
|
|
||||||
|
String finalVersion = version;
|
||||||
|
Bukkit.getScheduler().runTask(this.plugin, () -> this.versionResponse.accept(latestVersion ? VersionResponse.LATEST : VersionResponse.FOUND_NEW, latestVersion ? this.currentVersion : finalVersion));
|
||||||
|
} catch (IOException | NullPointerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Bukkit.getScheduler().runTask(this.plugin, () -> this.versionResponse.accept(VersionResponse.UNAVAILABLE, null));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CheckType {
|
||||||
|
SPIGOT, SBDPLUGINS
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum VersionResponse {
|
||||||
|
LATEST, FOUND_NEW, UNAVAILABLE
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
src/main/resources/message.yml
Normal file
14
src/main/resources/message.yml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
version: 1.0
|
||||||
|
|
||||||
|
prefix: '&6&lThemeParkConnectorMC &r&f➢'
|
||||||
|
|
||||||
|
client:
|
||||||
|
connect:
|
||||||
|
click: "{prefix} &fClick here to connect to the &6&lRideOperator"
|
||||||
|
hover: "&6Minecraft will prompt you to open the web client when you click this message"
|
||||||
|
unable: "{prefix} &4Currently unable to generate a session"
|
||||||
|
generate: "{prefix} &6Attempting to generate session..."
|
||||||
|
connection:
|
||||||
|
exists: "{prefix} &4Already connected to RideOperator"
|
||||||
|
open: "{prefix} &aSuccessfully connected to RideOperator"
|
||||||
|
closed: "{prefix} &4Connection with RideOperator was closed"
|
11
src/main/resources/plugin.yml
Normal file
11
src/main/resources/plugin.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
name: ThemeParkConnector
|
||||||
|
version: 3.0.0
|
||||||
|
author: IOByte
|
||||||
|
website: 'https://www.iobyte.nl'
|
||||||
|
main: nl.iobyte.themeparkconnector.ThemeParkConnector
|
||||||
|
depend: [ThemePark]
|
||||||
|
softdepend: [Vault,PlaceholderAPI,Train_Carts,Multiverse-Core,MultiWorld]
|
||||||
|
api-version: 1.13
|
||||||
|
commands:
|
||||||
|
tpc:
|
||||||
|
aliases: [themeparkconnector]
|
16
src/main/resources/settings.yml
Normal file
16
src/main/resources/settings.yml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
version: 1.0
|
||||||
|
|
||||||
|
license: ''
|
||||||
|
|
||||||
|
socket:
|
||||||
|
id: 'themepark'
|
||||||
|
url: 'websocket.iobyte.nl'
|
||||||
|
panel: 'panel.example.com/control/%ID%/%TOKEN%'
|
||||||
|
|
||||||
|
sign:
|
||||||
|
control:
|
||||||
|
name: '[Operator]'
|
||||||
|
title: '&f[&6&lOperator&f]'
|
||||||
|
scan:
|
||||||
|
name: '[TicketScan]'
|
||||||
|
title: '&f[&6&lTicketScan&f]'
|
35
themeparkconnector.iml
Normal file
35
themeparkconnector.iml
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_11">
|
||||||
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: commons-lang:commons-lang:2.6" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: junit:junit:4.10" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:21.0" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.gson:gson:2.8.0" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: org.yaml:snakeyaml:1.19" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: net.md-5:bungeecord-chat:1.12-SNAPSHOT" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: io.socket:socket.io-client:1.0.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: io.socket:engine.io-client:1.0.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.squareup.okhttp3:okhttp:3.12.12" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: com.squareup.okio:okio:1.15.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: org.json:json:20090211" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: nl.iobyte:themepark:3.0.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: de.mkammerer.snowflake-id:snowflake-id:0.0.1" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: de.tr7zw:item-nbt-api:2.8.0" level="project" />
|
||||||
|
<orderEntry type="library" name="Maven: de.tr7zw:functional-annotations:0.1-SNAPSHOT" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: net.milkbowl.vault:VaultAPI:1.7" level="project" />
|
||||||
|
<orderEntry type="library" scope="PROVIDED" name="Maven: org.bukkit:bukkit:1.13.1-R0.1-SNAPSHOT" level="project" />
|
||||||
|
</component>
|
||||||
|
</module>
|
Reference in a new issue