All src
This commit is contained in:
commit
6550dcd9e8
|
@ -0,0 +1,8 @@
|
|||
|
||||
\.idea/
|
||||
|
||||
target/classes/
|
||||
|
||||
target/
|
||||
|
||||
*.iml
|
|
@ -0,0 +1,2 @@
|
|||
First commit.
|
||||
test
|
|
@ -0,0 +1,146 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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>
|
||||
|
||||
<groupId>net.grandtheftmc</groupId>
|
||||
<artifactId>bungee</artifactId>
|
||||
<version>1.0.6</version>
|
||||
<name>Bungee</name>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>bungee-repo</id>
|
||||
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>md_5-snapshots</id>
|
||||
<url>http://repo.md-5.net/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>nexus-release</id>
|
||||
<url>http://nexus.grandtheftmc.net/content/repositories/releases</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>nexus-release</id>
|
||||
<name>Internal Releases</name>
|
||||
<url>http://nexus.grandtheftmc.net/content/repositories/releases</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>nexus-snapshot</id>
|
||||
<name>Internal Snapshots</name>
|
||||
<url>http://nexus.grandtheftmc.net/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>LATEST</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.imaginarycode.minecraft</groupId>
|
||||
<artifactId>RedisBungee</artifactId>
|
||||
<version>0.3.6-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20131018</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.authy</groupId>
|
||||
<artifactId>authy-java</artifactId>
|
||||
<version>LATEST</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.grandtheftmc</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>21.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>LATEST</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>2.6.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<configuration>
|
||||
<finalName>Bungee</finalName>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- Nexus deploy -->
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.6.8</version>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-deploy</id>
|
||||
<phase>deploy</phase>
|
||||
<goals>
|
||||
<goal>deploy</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<serverId>nexus</serverId>
|
||||
<nexusUrl>http://nexus.grandtheftmc.net/</nexusUrl>
|
||||
<skipStaging>true</skipStaging>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,305 @@
|
|||
package net.grandtheftmc.Bungee;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.RedisBungee;
|
||||
|
||||
import net.grandtheftmc.ServerType;
|
||||
import net.grandtheftmc.ServerTypeId;
|
||||
import net.grandtheftmc.Bungee.authy.AuthyManager;
|
||||
import net.grandtheftmc.Bungee.commands.AuthyCommand;
|
||||
import net.grandtheftmc.Bungee.commands.FindCommand;
|
||||
import net.grandtheftmc.Bungee.commands.GlobalMessageCommand;
|
||||
import net.grandtheftmc.Bungee.commands.HelpCommand;
|
||||
import net.grandtheftmc.Bungee.commands.HubCommand;
|
||||
import net.grandtheftmc.Bungee.commands.MotdCommand;
|
||||
import net.grandtheftmc.Bungee.commands.PermsCommand;
|
||||
import net.grandtheftmc.Bungee.commands.PlaytimeCommand;
|
||||
import net.grandtheftmc.Bungee.commands.ServerCommand;
|
||||
import net.grandtheftmc.Bungee.commands.StaffChatCommand;
|
||||
import net.grandtheftmc.Bungee.database.BaseDatabase;
|
||||
import net.grandtheftmc.Bungee.help.HelpCore;
|
||||
import net.grandtheftmc.Bungee.listeners.Chat;
|
||||
import net.grandtheftmc.Bungee.listeners.Connect;
|
||||
import net.grandtheftmc.Bungee.listeners.Disconnect;
|
||||
import net.grandtheftmc.Bungee.listeners.Kick;
|
||||
import net.grandtheftmc.Bungee.listeners.Login;
|
||||
import net.grandtheftmc.Bungee.listeners.Ping;
|
||||
import net.grandtheftmc.Bungee.redisbungee.RedisListener;
|
||||
import net.grandtheftmc.Bungee.redisbungee.RedisManager;
|
||||
import net.grandtheftmc.Bungee.tasks.AnnouncerTask;
|
||||
import net.grandtheftmc.Bungee.tasks.AuthyTask;
|
||||
import net.grandtheftmc.Bungee.tasks.PlaytimePurgeTask;
|
||||
import net.grandtheftmc.Bungee.tasks.ServerStatusTask;
|
||||
import net.grandtheftmc.Bungee.users.UserManager;
|
||||
import net.grandtheftmc.jedis.JMessageListener;
|
||||
import net.grandtheftmc.jedis.JedisChannel;
|
||||
import net.grandtheftmc.jedis.JedisManager;
|
||||
import net.grandtheftmc.jedis.message.ServerJoinRequestMessage;
|
||||
import net.grandtheftmc.slack.Slack;
|
||||
import net.grandtheftmc.slack.SlackChannel;
|
||||
import net.grandtheftmc.slack.SlackField;
|
||||
import net.grandtheftmc.slack.SlackHook;
|
||||
import net.grandtheftmc.slack.attachment.SlackAttachment;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.api.plugin.PluginManager;
|
||||
import net.md_5.bungee.api.scheduler.ScheduledTask;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
|
||||
public class Bungee extends Plugin implements Listener {
|
||||
|
||||
// TODO remove
|
||||
// test commit
|
||||
|
||||
private static Bungee instance;
|
||||
private RedisManager redisManager;
|
||||
private AuthyManager authyManager;
|
||||
private Settings settings;
|
||||
private UserManager um;
|
||||
private JedisManager jedisManager;
|
||||
|
||||
public boolean enabled = false;
|
||||
|
||||
public static final boolean GTM = true;
|
||||
|
||||
private HelpCore helpCore;
|
||||
|
||||
private Long startTime;
|
||||
private ScheduledTask task69;
|
||||
|
||||
public static Bungee getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static Settings getSettings() {
|
||||
return instance.settings;
|
||||
}
|
||||
|
||||
public static UserManager getUserManager() {
|
||||
return instance.um;
|
||||
}
|
||||
|
||||
public static RedisManager getRedisManager() {
|
||||
return instance.redisManager;
|
||||
}
|
||||
|
||||
public static AuthyManager getAuthyManager() {
|
||||
return instance.authyManager;
|
||||
}
|
||||
|
||||
public static void log(String msg) {
|
||||
Bungee.getInstance().getLogger().log(Level.INFO, msg);
|
||||
}
|
||||
|
||||
public static void error(String msg) {
|
||||
Bungee.getInstance().getLogger().log(Level.SEVERE, msg);
|
||||
}
|
||||
|
||||
public static void consoleLog(String log) {
|
||||
}
|
||||
|
||||
public HelpCore getHelpCore() {
|
||||
return helpCore;
|
||||
}
|
||||
|
||||
public Long getStartTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
|
||||
getProxy().getScheduler().runAsync(this, () -> {
|
||||
this.jedisManager = new JedisManager();
|
||||
this.jedisManager.initModule(new ServerTypeId(ServerType.PROXY, -1), JedisChannel.SERVER_QUEUE, GTM ? "172.16.0.1" : "databasesql", 5555, GTM ? "gtmredispass" : "redispass");
|
||||
this.jedisManager.getModule(JedisChannel.SERVER_QUEUE).registerListener(ServerJoinRequestMessage.class, new QueueListener());
|
||||
});
|
||||
|
||||
this.settings = new Settings();
|
||||
this.load();
|
||||
this.um = new UserManager();
|
||||
this.registerCommands();
|
||||
this.registerListeners();
|
||||
new AnnouncerTask();
|
||||
new ServerStatusTask();
|
||||
new PlaytimePurgeTask();
|
||||
new AuthyTask();
|
||||
this.startTime = System.currentTimeMillis();
|
||||
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if(this.task69 != null && this.task69.getTask() != null)
|
||||
this.task69.cancel();
|
||||
|
||||
for(JedisChannel channel : this.jedisManager.getJedisModules().keySet()) {
|
||||
this.jedisManager.getModule(channel).disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerCommands() {
|
||||
PluginManager pm = ProxyServer.getInstance().getPluginManager();
|
||||
for (String st : this.settings.getServers().keySet())
|
||||
pm.registerCommand(this, new ServerCommand(st, this.jedisManager));
|
||||
// pm.registerCommand(this, new AltCommand());
|
||||
pm.registerCommand(this, new GlobalMessageCommand());
|
||||
pm.registerCommand(this, new HelpCommand());
|
||||
pm.registerCommand(this, new HubCommand(this.jedisManager, "hub"));
|
||||
pm.registerCommand(this, new HubCommand(this.jedisManager, "lobby"));
|
||||
pm.registerCommand(this, new HubCommand(this.jedisManager, "gtm"));
|
||||
pm.registerCommand(this, new HubCommand(this.jedisManager, "vice"));
|
||||
pm.registerCommand(this, new MotdCommand());
|
||||
pm.registerCommand(this, new PermsCommand());
|
||||
// pm.registerCommand(this, new SeenCommand());
|
||||
pm.registerCommand(this, new StaffChatCommand());
|
||||
pm.registerCommand(this, new PlaytimeCommand());
|
||||
pm.registerCommand(this, new AuthyCommand());
|
||||
pm.registerCommand(this, new FindCommand());
|
||||
}
|
||||
|
||||
private void registerListeners() {
|
||||
PluginManager pm = ProxyServer.getInstance().getPluginManager();
|
||||
pm.registerListener(this, new Chat());
|
||||
pm.registerListener(this, new Disconnect());
|
||||
pm.registerListener(this, new Login());
|
||||
pm.registerListener(this, new Connect());
|
||||
pm.registerListener(this, new Kick());
|
||||
pm.registerListener(this, new Ping());
|
||||
pm.registerListener(this, new RedisListener());
|
||||
|
||||
getRedisManager().getRedisAPI().registerPubSubChannels(getRedisManager().getMessageChannel());
|
||||
}
|
||||
|
||||
private void load() {
|
||||
this.settings.setMySQLConfig(Utils.loadConfigFromMaster("mysql"));
|
||||
// this.settings.setBATConfig(BAT.getInstance().getConfiguration());
|
||||
this.settings.setPermsConfig(Utils.loadConfig("perms"));
|
||||
this.settings.setMotdConfig(Utils.loadConfig("motd"));
|
||||
this.settings.setGtmConfig(Utils.loadConfig("gtmconfig"));
|
||||
|
||||
this.settings.setHelpConfig(Utils.loadConfig("help"));
|
||||
//Init help core.
|
||||
this.helpCore = new HelpCore(this.settings.getHelpConfiguration());
|
||||
|
||||
this.settings.setMotd(this.settings.getMotdConfig().getString("motd"));
|
||||
this.loadMySQL();
|
||||
if (this.getProxy().getPluginManager().getPlugin("RedisBungee") != null) {
|
||||
this.redisManager = new RedisManager(RedisBungee.getApi());
|
||||
} else {
|
||||
error("RedisBungee not found!");
|
||||
}
|
||||
|
||||
this.authyManager = new AuthyManager();
|
||||
}
|
||||
|
||||
private void loadMySQL() {
|
||||
Configuration c = this.settings.getMySQLConfig();
|
||||
this.settings.setHost(c.getString("mysql.host"));
|
||||
this.settings.setPort(c.getString("mysql.port"));
|
||||
this.settings.setDatabase(c.getString("mysql.database"));
|
||||
this.settings.setUser(c.getString("mysql.user"));
|
||||
this.settings.setPassword(c.getString("mysql.password"));
|
||||
|
||||
BaseDatabase.getInstance().init(
|
||||
this.settings.getHost(),
|
||||
Integer.parseInt(this.settings.getPort()),
|
||||
this.settings.getDatabase(),
|
||||
this.settings.getUser(),
|
||||
this.settings.getPassword()
|
||||
);
|
||||
}
|
||||
|
||||
private void initHubPinger() {
|
||||
for (String str : getProxy().getServers().keySet()) {
|
||||
Utils.SERVERS.putIfAbsent(getProxy().getServerInfo(str), true);
|
||||
}
|
||||
|
||||
task69 = getProxy().getScheduler().schedule(this, () -> {
|
||||
for(ServerInfo server : Utils.SERVERS.keySet()) {
|
||||
if(!Utils.SERVERS.get(server)) continue;
|
||||
getProxy().getScheduler().runAsync(this, () -> server.ping((serverPing, throwable) -> {
|
||||
if(throwable != null) {
|
||||
Utils.SERVERS.put(server, false);
|
||||
|
||||
String[] serv = getServerType(server.getName());
|
||||
Slack.send(SlackChannel.PRODUCTION_ALERTS, SlackHook.SERVER_HEARTBEAT,
|
||||
new SlackAttachment("Server down! " + server.getName())
|
||||
.setColor("#e01563")
|
||||
.setAuthorName("BungeeCord")
|
||||
.addFields(
|
||||
new SlackField().setTitle("Server Type").setValue(serv[0]).setShorten(true)
|
||||
)
|
||||
.addFields(
|
||||
new SlackField().setTitle("Identifier").setValue(serv[1]).setShorten(true)
|
||||
)
|
||||
.addFields(
|
||||
new SlackField().setTitle("Triggered By").setValue(throwable.getLocalizedMessage()).setShorten(false)
|
||||
)
|
||||
.setFooter("Timestamp")
|
||||
);
|
||||
}
|
||||
else {
|
||||
Utils.SERVERS.put(server, true);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}, 10, 30, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public String[] getServerType(String server) {
|
||||
String id = "-1";
|
||||
ServerType type = ServerType.OPERATOR;
|
||||
if(server.toLowerCase().startsWith("hub")) {
|
||||
id = server.toLowerCase().split("hub")[1];
|
||||
type = ServerType.HUB;
|
||||
}
|
||||
|
||||
if(server.toLowerCase().startsWith("gtm")) {
|
||||
id = server.toLowerCase().split("gtm")[1];
|
||||
type = ServerType.GTM;
|
||||
}
|
||||
|
||||
if(server.toLowerCase().startsWith("vice")) {
|
||||
id = server.toLowerCase().split("vice")[1];
|
||||
type = ServerType.VICE;
|
||||
}
|
||||
|
||||
if(server.toLowerCase().startsWith("creative")) {
|
||||
id = server.toLowerCase().split("creative")[1];
|
||||
type = ServerType.CREATIVE;
|
||||
}
|
||||
|
||||
return new String[]{ type == ServerType.OPERATOR ? server.toUpperCase() : type.name(), id };
|
||||
}
|
||||
|
||||
public class QueueListener implements JMessageListener<ServerJoinRequestMessage> {
|
||||
|
||||
@Override
|
||||
public void onReceive(ServerTypeId serverTypeId, ServerJoinRequestMessage message) {
|
||||
if(!enabled) return;
|
||||
|
||||
ProxiedPlayer player = instance.getProxy().getPlayer(message.getUniqueId());
|
||||
if(player == null) return;
|
||||
ServerInfo info = instance.getProxy().getServerInfo(message.getTargetServer().getServerType().getServerName() + message.getTargetServer().getId());
|
||||
if(info != null) {
|
||||
info.ping((serverPing, throwable) -> {
|
||||
if(serverPing != null) {
|
||||
player.connect(info);
|
||||
player.sendMessage(Utils.f("&aSending you to server!"));
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
player.sendMessage(Utils.f("&cThis server cannot be recognised!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package net.grandtheftmc.Bungee;
|
||||
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
|
||||
public enum Lang {
|
||||
|
||||
GMSG(" &a&lGMSG&8&l> "),
|
||||
MSG(" &a&lMSG&8&l> "),
|
||||
BUCKS(" &a&lBUCKS&8&l> "),
|
||||
BUCKS_ADD(" &a&lBUCKS&8&l> &a&l+&a $&l"),
|
||||
BUCKS_TAKE(" &a&lBUCKS&8&l> &c&l-&c $&l"),
|
||||
TOKENS(" &e&lTOKENS&8&l> "),
|
||||
TOKENS_ADD(" &e&lTOKENS&8&l> &e&l+&e&l"),
|
||||
TOKENS_TAKE(" &e&lTOKENS&8&l> &c&l-&c&l"),
|
||||
MONEY(" &3&lMONEY&8&l> "),
|
||||
MONEY_ADD(" &3&lMONEY&8&l> &a&l+&a $&l"),
|
||||
MONEY_TAKE(" &3&lMONEY&8&l> &c&l-&c $&l"),
|
||||
ATM(" &3&lATM&8&l> "),
|
||||
BANK(" &3&lBANK&8&l> "),
|
||||
BANK_ADD("&3&lBANK&8&l> &a&l+&a $&l"),
|
||||
BANK_TAKE("&3&lBANK&8&l> &c&l-&c $&l"),
|
||||
GTM(" &7&l" + (Bungee.GTM ? "GTM" : "GTA") + "&8&l> "),
|
||||
PREFS(" &5&lPREFS&8&l> "),
|
||||
AMMUNATION(" &9&lAMMU&4&lNATION&8&l> "),
|
||||
WANTED(" &c&lWANTED&8&l> "),
|
||||
TAXI(" &e&lTAXI&8&l> "),
|
||||
SHOP(" &a&lSHOP&8&l> "),
|
||||
TRASH_CAN(" &7&lTRASH CAN&8&l> "),
|
||||
HEY(" &c&lHEY&8&l> "),
|
||||
COMBATTAG(" &7&lCOMBATTAG&8&l> "),
|
||||
GUARDPETS("&c&l GUARD PETS&8&l> "),
|
||||
BOUNTIES(" &5&lBOUNTIES&8&l> "),
|
||||
VOTE(" &e&lVOTE&8&l> "),
|
||||
TOKEN_SHOP(" &e&lTOKEN SHOP&8&l> "),
|
||||
KITS(" &b&lKITS&8&l> "),
|
||||
RANKUP(" &a&lRANKUP&8&l> "),
|
||||
RANKS(" &a&lRANKS&8&l> "),
|
||||
JOBS(" &3&lJOBS&8&l> "),
|
||||
COP_MODE(" &3&lCOP MODE&8&l> "),
|
||||
HITMAN_MODE(" &8&lHITMAN MODE> "),
|
||||
GPS(" &7&lGPS&8&l> "),
|
||||
HOUSES(" &3&lHOUSES&8&l> "),
|
||||
TUTORIALS(" &2&lTUTORIALS&8&l> "),
|
||||
GANGS(" &a&lGANGS&8&l> "),
|
||||
NOPERM("&cYou want me to clap yo ass? You ain't got permission for this shit!"),
|
||||
NOTPLAYER("&cDawg you ain't a player!"),
|
||||
STAFF(" &c&lSTAFF&8&l> "),
|
||||
HELP(" &d&lHELP&8&l> "),
|
||||
GSPY(" &a&lGSPY&8&l> "),
|
||||
PERMS(" &c&lGPERMS&8&l> "),
|
||||
VERIFICATION(" &c&lVERIFICATION&8&l> ");
|
||||
|
||||
private final String s;
|
||||
|
||||
Lang(String s) {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
public String s() {
|
||||
return Utils.f(this.s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Utils.f(this.s);
|
||||
}
|
||||
|
||||
public String f(String s) {
|
||||
return Utils.f(this.s + s);
|
||||
}
|
||||
|
||||
public TextComponent ft(String s) {
|
||||
return Utils.ft(this.s + s);
|
||||
}
|
||||
|
||||
public TextComponent st() {
|
||||
return Utils.ft(this.s);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package net.grandtheftmc.Bungee;
|
||||
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class Settings {
|
||||
private final Map<String, String> servers = new HashMap<>();
|
||||
private Configuration config;
|
||||
private Configuration mysqlConfig;
|
||||
private Configuration permsConfig;
|
||||
private Configuration motdConfig;
|
||||
private Configuration helpConfig;
|
||||
private Configuration gtmConfig;
|
||||
private String motd;
|
||||
private String host = "error";
|
||||
private String port = "error";
|
||||
private String database = "error";
|
||||
private String user = "error";
|
||||
private String password = "error";
|
||||
|
||||
Settings() {
|
||||
this.servers.clear();
|
||||
Set<String> s = ProxyServer.getInstance().getServers().keySet();
|
||||
for (String c : s)
|
||||
this.servers.put(c, c);
|
||||
this.servers.put("creative", "creative1");
|
||||
this.servers.put("crea", "creative1");
|
||||
this.servers.put("gtm", "gtm1");
|
||||
this.servers.put("legacy", "legacygtm");
|
||||
this.servers.put("gtmlegacy", "legacygtm");
|
||||
this.servers.put("oldgtm", "legacy");
|
||||
this.servers.put("gliders", "gliders1");
|
||||
this.servers.put("dev", "gtm0");
|
||||
this.servers.put("vice","vice1");
|
||||
}
|
||||
|
||||
public Configuration getMySQLConfig() {
|
||||
return this.mysqlConfig;
|
||||
}
|
||||
|
||||
public void setMySQLConfig(Configuration mysqlConfig) {
|
||||
this.mysqlConfig = mysqlConfig;
|
||||
}
|
||||
|
||||
public Configuration getHelpConfiguration(){
|
||||
return this.helpConfig;
|
||||
}
|
||||
|
||||
public void setHelpConfig(Configuration config) {
|
||||
this.helpConfig = config;
|
||||
}
|
||||
|
||||
public Map<String, String> getServers() {
|
||||
return this.servers;
|
||||
}
|
||||
|
||||
public Configuration getPermsConfig() {
|
||||
return this.permsConfig;
|
||||
}
|
||||
|
||||
public void setPermsConfig(Configuration permsConfig) {
|
||||
this.permsConfig = permsConfig;
|
||||
}
|
||||
|
||||
public String getMotd() {
|
||||
return Utils.f(this.motd);
|
||||
}
|
||||
|
||||
public void setMotd(String motd) {
|
||||
this.motd = motd;
|
||||
}
|
||||
|
||||
public Configuration getMotdConfig() {
|
||||
return this.motdConfig;
|
||||
}
|
||||
|
||||
public void setMotdConfig(Configuration motdConfig) {
|
||||
this.motdConfig = motdConfig;
|
||||
}
|
||||
|
||||
public Configuration getGtmConfig() {
|
||||
return this.gtmConfig;
|
||||
}
|
||||
|
||||
public void setGtmConfig(Configuration gtmConfig) {
|
||||
this.gtmConfig = gtmConfig;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return this.host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public String getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
public void setPort(String port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getDatabase() {
|
||||
return this.database;
|
||||
}
|
||||
|
||||
public void setDatabase(String database) {
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return this.user;
|
||||
}
|
||||
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,386 @@
|
|||
package net.grandtheftmc.Bungee;
|
||||
|
||||
import net.grandtheftmc.Bungee.redisbungee.data.DataType;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.users.UserRank;
|
||||
import net.grandtheftmc.Bungee.utils.DefaultFontInfo;
|
||||
import net.grandtheftmc.Bungee.utils.ServerStatus;
|
||||
import net.grandtheftmc.Bungee.utils.TimeFormatter;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.*;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
import net.md_5.bungee.config.ConfigurationProvider;
|
||||
import net.md_5.bungee.config.YamlConfiguration;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class Utils {
|
||||
public static final ConcurrentHashMap<ServerInfo, Boolean> SERVERS = new ConcurrentHashMap<>();
|
||||
private static final Random RANDOM = new Random();
|
||||
public static Collection<String> recentHelps = new ArrayList<>();
|
||||
|
||||
private Utils() {
|
||||
}
|
||||
|
||||
public static TextComponent ft(String s) {
|
||||
return new TextComponent(ChatColor.translateAlternateColorCodes('&', s));
|
||||
}
|
||||
|
||||
public static String fc(String s) {
|
||||
s = Utils.f(s);
|
||||
int messagePxSize = 0;
|
||||
boolean previousCode = false;
|
||||
boolean isBold = false;
|
||||
|
||||
for (char c : s.toCharArray()) {
|
||||
if (c == '§') {
|
||||
previousCode = true;
|
||||
} else if (previousCode) {
|
||||
previousCode = false;
|
||||
isBold = c == 'l' || c == 'L';
|
||||
} else {
|
||||
DefaultFontInfo dFI = DefaultFontInfo.getDefaultFontInfo(c);
|
||||
messagePxSize += isBold ? dFI.getBoldLength() : dFI.getLength();
|
||||
messagePxSize++;
|
||||
}
|
||||
}
|
||||
|
||||
int halvedMessageSize = messagePxSize / 2;
|
||||
int toCompensate = 154 - halvedMessageSize;
|
||||
int spaceLength = DefaultFontInfo.SPACE.getLength() + 1;
|
||||
int compensated = 0;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (compensated < toCompensate) {
|
||||
sb.append(' ');
|
||||
compensated += spaceLength;
|
||||
}
|
||||
return sb + s;
|
||||
}
|
||||
|
||||
public static String[] fc(String[] array) {
|
||||
if (array == null)
|
||||
return null;
|
||||
String[] a = new String[array.length];
|
||||
for (int i = 0; i < array.length; i++)
|
||||
a[i] = Utils.fc(array[i]);
|
||||
return a;
|
||||
}
|
||||
|
||||
public static void loop(int amount, Runnable runnable) {
|
||||
for (int i = 0; i < amount; i++) runnable.run();
|
||||
}
|
||||
|
||||
public static String f(String s) {
|
||||
return ChatColor.translateAlternateColorCodes('&', s);
|
||||
}
|
||||
|
||||
public static void redisChatLog(String sender, String msg) {
|
||||
Map<String, Object> chatLogSerializd = new HashMap<>();
|
||||
chatLogSerializd.put("type", "staff");
|
||||
chatLogSerializd.put("sender", sender);
|
||||
chatLogSerializd.put("message", msg);
|
||||
Bungee.getRedisManager().sendMessage(Bungee.getRedisManager().serialize(DataType.LOG, chatLogSerializd));
|
||||
}
|
||||
|
||||
public static void chatLog(String sender, String msg) {
|
||||
String fileName = new SimpleDateFormat("MM-dd-yy").format(new Date());
|
||||
File file = new File("gtmlogs/gtmlog_staff_" + fileName + ".txt");
|
||||
try {
|
||||
if (!file.isFile() || !file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
String date = new SimpleDateFormat("MM/dd/yy - h:mm a").format(new Date());
|
||||
String message = date + " - " + sender + ": " + msg + "\n";
|
||||
FileWriter fileWriter = new FileWriter(file, true);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||
bufferedWriter.write(message);
|
||||
bufferedWriter.close();
|
||||
} catch (IOException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void log(String msg, String logName) {
|
||||
String fileName = new SimpleDateFormat("MM-dd-yy").format(new Date());
|
||||
File file = new File("gtmlogs/gtmlog_" + logName + "_" + fileName + ".txt");
|
||||
try {
|
||||
if (!file.isFile() || !file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
String date = new SimpleDateFormat("MM/dd/yy - h:mm a").format(new Date());
|
||||
String message = date + " - " + msg + "\n";
|
||||
FileWriter fileWriter = new FileWriter(file, true);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||
bufferedWriter.write(message);
|
||||
bufferedWriter.close();
|
||||
} catch (IOException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void redisStaffChat(String sender, String msg) {
|
||||
Map<String, Object> staffChatSerialized = new HashMap<>();
|
||||
staffChatSerialized.put("sender", sender);
|
||||
staffChatSerialized.put("message", msg);
|
||||
|
||||
Bungee.getRedisManager().sendMessage(Bungee.getRedisManager().serialize(DataType.STAFFCHAT, staffChatSerialized));
|
||||
}
|
||||
|
||||
public static void staffChat(String name, String msg) {
|
||||
String prefix = "&7[&a&l" + name + "&7] ";
|
||||
ComponentBuilder a = new ComponentBuilder(Lang.STAFF.f(prefix))
|
||||
.append(msg)
|
||||
.color(ChatColor.GREEN);
|
||||
for (String string : msg.split(" ")) {
|
||||
if (string.matches("^((https?|ftp)://|(www|ftp)\\.)?[a-z0-9-]+(\\.[a-z0-9-]+)+([/?].*)?$")) {
|
||||
a.event(new ClickEvent(ClickEvent.Action.OPEN_URL, string));
|
||||
break;
|
||||
}
|
||||
}
|
||||
ProxyServer.getInstance().getPlayers().stream().filter(player -> player.hasPermission("staffchat.use")).forEach(player -> player.sendMessage(a.create()));
|
||||
Bungee.log(Lang.STAFF.f("[" + name + "] " + msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a help request has been invoked on the Redis listener. This forwards the request to all staff.
|
||||
*
|
||||
* @param playerName Player who requested help.
|
||||
* @param msg What did they ask for help with?
|
||||
* @param server What server is the player on.
|
||||
*/
|
||||
public static void redisHelp(String playerName, String msg, String server) {
|
||||
//can't pass proxy player here as staff and help requester may be on different instances
|
||||
BaseComponent[] a = new ComponentBuilder(Lang.HELP.f("&7[&8" + playerName + "&7] "))
|
||||
.append(msg)
|
||||
.color(ChatColor.GREEN)
|
||||
.event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/gmsg " + playerName + " "))
|
||||
.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(Utils.f("&7User is on server &a" + server)).create()))
|
||||
.create();
|
||||
|
||||
ProxyServer.getInstance().getPlayers().stream().filter(p -> p.hasPermission("staffchat.use") || p.getName().equalsIgnoreCase(playerName)).forEach(p -> p.sendMessage(a));
|
||||
Bungee.log(Lang.HELP.f("&7[&8" + playerName + "&7] &r" + msg));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void help(ProxiedPlayer player, String msg) {
|
||||
if (msg.split(" ").length <= 1) {
|
||||
player.sendMessage(Lang.HELP.f("&7Only one word? Try to describe your problem more accurately."));
|
||||
return;
|
||||
}
|
||||
|
||||
String name = getColoredName(player);
|
||||
BaseComponent[] a = new ComponentBuilder(Lang.HELP.f("&7[&a&l" + name + "&7] "))
|
||||
.append(msg).color(ChatColor.GREEN)
|
||||
.event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/gmsg " + player.getName() + " "))
|
||||
.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(Utils.f("&7User is on server &a" + player.getServer().getInfo().getName())).create()))
|
||||
.create();
|
||||
|
||||
ProxyServer.getInstance().getPlayers().stream().filter(p -> p.hasPermission("staffchat.use") || p.equals(player)).forEach(p -> p.sendMessage(a));
|
||||
Bungee.log(Lang.HELP.f("&7[&a&l" + name + "&7] &r" + msg));
|
||||
player.sendMessage(Lang.HELP.f("&7Your message has been sent to all online staff. Use &a&l\"/gmsg <name>\"&7 to talk to them individually."));
|
||||
addRecentHelp(player.getName());
|
||||
}
|
||||
|
||||
public static void msg(ProxiedPlayer player, String msg) {
|
||||
player.sendMessage(ft(msg));
|
||||
}
|
||||
|
||||
public static void msg(CommandSender player, String msg) {
|
||||
player.sendMessage(ft(msg));
|
||||
}
|
||||
|
||||
public static void redisGlobalMessage(ProxiedPlayer sender, String target, String msg) {
|
||||
if (!Bungee.getRedisManager().isPlayerOnline(target)) {
|
||||
msg(sender, "&7That player is not on the server!");
|
||||
return;
|
||||
}
|
||||
|
||||
String to = Lang.GMSG.f("&7[" + getColoredName(sender) + "&7 -> me] &r" + msg);
|
||||
String from = Lang.GMSG.f("&7[me -> " + getColoredName(target) + "&7] &r" + msg);
|
||||
String ss = Lang.GSPY.f("&7[" + getColoredName(sender) + "&7 -> " + getColoredName(target) + "&7] &r" + msg);
|
||||
msg(sender, from);
|
||||
|
||||
Map<String, Object> toSerialized = new HashMap<>();
|
||||
toSerialized.put("sender", sender.getName());
|
||||
toSerialized.put("target", target);
|
||||
toSerialized.put("message", to);
|
||||
Bungee.getRedisManager().sendMessage(Bungee.getRedisManager().serialize(DataType.GMSG, toSerialized));
|
||||
|
||||
|
||||
Map<String, Object> socialSpySerialized = new HashMap<>();
|
||||
socialSpySerialized.put("message", ss);
|
||||
Bungee.getRedisManager().sendMessage(Bungee.getRedisManager().serialize(DataType.SOCIALSPY, socialSpySerialized));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void globalMessage(ProxiedPlayer sender, ProxiedPlayer target, String msg) {
|
||||
if (target == null) {
|
||||
msg(sender, "&7That player is not on the server!");
|
||||
return;
|
||||
}
|
||||
|
||||
String to = Lang.GMSG.f("&7[" + getColoredName(sender) + "&7 -> me] &r" + msg);
|
||||
String from = Lang.GMSG.f("&7[me -> " + getColoredName(target) + "&7] &r" + msg);
|
||||
String ss = Lang.GSPY.f("&7[" + getColoredName(sender) + "&7 -> " + getColoredName(target) + "&7] &r" + msg);
|
||||
String url = "";
|
||||
for (String string : msg.split(" ")) {
|
||||
if (string.matches("^((https?|ftp)://|(www|ftp)\\.)?[a-z0-9-]+(\\.[a-z0-9-]+)+([/?].*)?$")) {
|
||||
url = string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BaseComponent[] a = new ComponentBuilder(to)
|
||||
.event(url.isEmpty() ? new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/gmsg " + sender.getName() + " ")
|
||||
: new ClickEvent(ClickEvent.Action.OPEN_URL, url))
|
||||
.create();
|
||||
target.sendMessage(a);
|
||||
msg(sender, from);
|
||||
Bungee.log(Lang.GMSG.f("&7[" + sender.getName() + " -> " + target.getName() + "&7] &r" + msg));
|
||||
log("[" + sender.getName() + " -> " + target.getName() + "] " + msg, "gmsglog");
|
||||
socialSpy(ss, sender, target);
|
||||
}
|
||||
|
||||
public static void socialSpy(String msg, ProxiedPlayer sender, ProxiedPlayer target) {
|
||||
Bungee.getUserManager().getLoadedUsers().forEach(user -> {
|
||||
if (Bungee.getInstance().getProxy().getPlayer(user.getUUID()) == null) return;
|
||||
if (!user.isRank(UserRank.ADMIN)) return;
|
||||
ProxiedPlayer staff = Bungee.getInstance().getProxy().getPlayer(user.getUUID());
|
||||
if (user.getSocialSpy()) {
|
||||
if (!staff.getName().equals(sender.getName()) || !staff.getName().equals(target.getName())) {
|
||||
staff.sendMessage(Utils.f(msg));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Configuration loadConfigFile(File file) {
|
||||
Configuration c = null;
|
||||
try {
|
||||
if (!file.exists())
|
||||
file.createNewFile();
|
||||
c = ConfigurationProvider.getProvider(YamlConfiguration.class).load(file);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public static Configuration loadConfig(String src) {
|
||||
return loadConfigFile(new File(src + ".yml"));
|
||||
}
|
||||
|
||||
public static Configuration loadConfigFromMaps(String src) {
|
||||
return loadConfigFile(new File("/home/mcservers/development/master/maps/" + src + ".yml"));
|
||||
}
|
||||
|
||||
public static Configuration loadConfigFromMaster(String src) {
|
||||
return loadConfigFile(new File("/home/mcservers/development/master/" + src + ".yml"));
|
||||
}
|
||||
|
||||
public static void saveConfigFile(Configuration c, File file) {
|
||||
try {
|
||||
if (!file.exists())
|
||||
file.createNewFile();
|
||||
ConfigurationProvider.getProvider(YamlConfiguration.class).save(c, file);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveConfig(Configuration c, String src) {
|
||||
saveConfigFile(c, new File(src + ".yml"));
|
||||
}
|
||||
|
||||
public static Random getRandom() {
|
||||
return RANDOM;
|
||||
}
|
||||
|
||||
public static List<String> getPlayerNames() {
|
||||
return ProxyServer.getInstance().getPlayers().stream().map(CommandSender::getName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static void addRecentHelp(String player) {
|
||||
recentHelps.add(player);
|
||||
Bungee.getInstance().getProxy().getScheduler().schedule(Bungee.getInstance(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
recentHelps.remove(player);
|
||||
}
|
||||
}, 30, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public static ServerInfo getRandomHub() {
|
||||
List<ServerInfo> hubs = Bungee.getInstance().getProxy().getServers().entrySet().stream().filter(map -> map.getKey().startsWith("hub")).map(Map.Entry::getValue).collect(Collectors.toList());
|
||||
return getLeastPlayers(hubs).orElse(hubs.get(Utils.getRandom().nextInt(hubs.size())));
|
||||
}
|
||||
|
||||
public static ServerInfo getRandomServer(String type) {
|
||||
List<ServerInfo> servs = Bungee.getInstance().getProxy().getServers().entrySet().stream().filter(map -> map.getKey().startsWith(type)).map(Map.Entry::getValue).collect(Collectors.toList());
|
||||
return getLeastPlayers(servs).orElse(servs.get(Utils.getRandom().nextInt(servs.size())));
|
||||
}
|
||||
|
||||
public static Optional<ServerInfo> getLeastPlayers(Collection<ServerInfo> servers) {
|
||||
Optional<ServerInfo> leastPlayers = Optional.empty();
|
||||
for (ServerInfo server : servers) {
|
||||
if (!isOnline(server)) {
|
||||
Bungee.error(server.getName() + " is offline");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (server.getPlayers().isEmpty()) {
|
||||
leastPlayers = Optional.of(server);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!leastPlayers.isPresent()) {
|
||||
leastPlayers = Optional.of(server);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (server.getPlayers().size() < leastPlayers.get().getPlayers().size()) {
|
||||
leastPlayers = Optional.of(server);
|
||||
}
|
||||
}
|
||||
return leastPlayers;
|
||||
}
|
||||
|
||||
public static boolean isOnline(ServerInfo serverInfo) {
|
||||
ServerStatus serverStatus = ServerStatus.getServerStatus(serverInfo);
|
||||
return serverStatus.isOnline();
|
||||
}
|
||||
|
||||
public static String getColoredName(ProxiedPlayer player) {
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(player.getUniqueId());
|
||||
return Utils.f(userOptional.map(user -> Utils.f(user.getUserRank().getColor() + player.getName())).orElseGet(() -> "&8" + player.getName()));
|
||||
}
|
||||
|
||||
public static String getColoredName(String player) {
|
||||
return Utils.f("&8" + player);
|
||||
}
|
||||
|
||||
public static String formatPlaytime(Long playtime) {
|
||||
TimeFormatter tf = new TimeFormatter(TimeUnit.MILLISECONDS, playtime);
|
||||
return tf.getHours() + "h " + tf.getMinutes() + "m";
|
||||
}
|
||||
|
||||
public static boolean isStaff(String name) {
|
||||
for (User user : Bungee.getUserManager().getLoadedUsers()) {
|
||||
if (user.getUsername().equalsIgnoreCase(name)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package net.grandtheftmc.Bungee.authy;
|
||||
|
||||
import com.authy.AuthyApiClient;
|
||||
import com.authy.api.Hash;
|
||||
import com.authy.api.Token;
|
||||
import com.authy.api.User;
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
|
||||
public class AuthyManager {
|
||||
private final String apiKey = Bungee.getSettings().getGtmConfig().getString("authy-api-key");
|
||||
private AuthyApiClient authyApiClient;
|
||||
|
||||
public AuthyManager() {
|
||||
init();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
this.authyApiClient = new AuthyApiClient(apiKey);
|
||||
}
|
||||
|
||||
public User createUser(String email, String phoneNumber, String countryCode) {
|
||||
return this.authyApiClient.getUsers().createUser(email, phoneNumber, countryCode);
|
||||
}
|
||||
|
||||
public String verifyToken(int authy_id, String userToken) {
|
||||
Token verification = this.authyApiClient.getTokens().verify(authy_id, userToken);
|
||||
if (verification.isOk()) {
|
||||
return "400";
|
||||
} else {
|
||||
return verification.getError().toString();
|
||||
}
|
||||
}
|
||||
|
||||
public String sendSMSToken(int authy_id) {
|
||||
Hash sms = this.authyApiClient.getUsers().requestSms(authy_id);
|
||||
if (sms.isOk()) {
|
||||
return "400";
|
||||
} else {
|
||||
return sms.getError().toString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
//import fr.Alphart.BAT.Modules.Core.LookupFormatter;
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.utils.RequestRateLimiter;
|
||||
import net.grandtheftmc.Bungee.utils.TabComplete;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AltCommand extends Command {
|
||||
|
||||
public AltCommand() {
|
||||
super("alt", "bat.lookup.ip", "alts");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
/*if (args.length != 1) {
|
||||
s.sendMessage(Utils.ft("&c/alt <player>"));
|
||||
return;
|
||||
}
|
||||
if (!(s instanceof ProxiedPlayer)) {
|
||||
s.sendMessage(Utils.ft("&cYou are not a player!"));
|
||||
return;
|
||||
}
|
||||
ProxiedPlayer p = (ProxiedPlayer) s;
|
||||
UUID sender = p.getUniqueId();
|
||||
|
||||
if (!RequestRateLimiter.requestCmd(sender)) {
|
||||
s.sendMessage(Utils.ft("&cYou have issued this command recently, please wait a second."));
|
||||
return;
|
||||
}
|
||||
|
||||
String player = args[0];
|
||||
s.sendMessage(Utils.ft("&7Looking up player &a" + player + "&7 in the database."));
|
||||
ProxyServer.getInstance().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
ResultSet rs = Bungee.getBATSQL()
|
||||
.query("select BAT_player,lastip from BAT_players where BAT_player='" + player + "';");
|
||||
String name1 = null;
|
||||
String lastip = null;
|
||||
try {
|
||||
if (rs.next()) {
|
||||
name1 = rs.getString("BAT_player");
|
||||
lastip = rs.getString("lastip");
|
||||
}
|
||||
rs.close();
|
||||
} catch (SQLException ignored) {
|
||||
|
||||
}
|
||||
ProxiedPlayer p1 = ProxyServer.getInstance().getPlayer(sender);
|
||||
if (p1 == null)
|
||||
return;
|
||||
// if (lastip == null || name1 == null || !fr.Alphart.BAT.Utils.Utils.validIP(lastip)) {
|
||||
// p1.sendMessage(Utils.ft("&7That player is not in the database!"));
|
||||
// return;
|
||||
// }
|
||||
// new LookupFormatter().getSummaryLookupIP(lastip).forEach(p1::sendMessage);
|
||||
});*/
|
||||
}
|
||||
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return TabComplete.onTabComplete(sender, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Lang;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class AuthyCommand extends Command {
|
||||
|
||||
public AuthyCommand() {
|
||||
super("authy", "authy.admin");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
if (!(s instanceof ProxiedPlayer)) return;
|
||||
ProxiedPlayer player = (ProxiedPlayer) s;
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(player.getUniqueId());
|
||||
if (!userOptional.isPresent()) return;
|
||||
User user = userOptional.get();
|
||||
if (args.length == 0) {
|
||||
sendHelp(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 1) {
|
||||
if (args[0].equalsIgnoreCase("help"))
|
||||
sendHelp(player);
|
||||
|
||||
else if (args[0].equalsIgnoreCase("countrycodes"))
|
||||
sendCountryCodes(player);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
else {
|
||||
if (user.isAuthyVerified()) {
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&7You are already verified!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[0].equalsIgnoreCase("verify")) {
|
||||
if (args.length != 2) {
|
||||
sendHelp(player);
|
||||
} else {
|
||||
String token = args[1];
|
||||
if (user.getAuthyId() == 0) {
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&cYou must register first!"));
|
||||
} else {
|
||||
String result = Bungee.getAuthyManager().verifyToken(user.getAuthyId(), token);
|
||||
if (result.equals("400")) {
|
||||
user.setAuthyVerified(true);
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&aVerification Successful"));
|
||||
user.setLastIPAddress(player.getAddress().getAddress().getHostAddress());
|
||||
} else {
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&cError! Verification Failed: " + result));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (args[0].equalsIgnoreCase("sendsms")) {
|
||||
if (user.getAuthyId() == 0) {
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&cYou must register first!"));
|
||||
} else {
|
||||
String result = Bungee.getAuthyManager().sendSMSToken(user.getAuthyId());
|
||||
if (result.equals("400")) {
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&aToken sent via SMS"));
|
||||
} else {
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&cError: " + result));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else if (args[0].equalsIgnoreCase("register")) {
|
||||
if (args.length != 4) {
|
||||
sendHelp(player);
|
||||
} else {
|
||||
String email = args[1];
|
||||
String phoneNumber = args[2];
|
||||
String countryCode = args[3];
|
||||
com.authy.api.User authyUser = Bungee.getAuthyManager().createUser(email, phoneNumber, countryCode);
|
||||
if (authyUser.isOk()) {
|
||||
user.setAuthyId(authyUser.getId());
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&aRegistration Successful"));
|
||||
}
|
||||
|
||||
else {
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&cError! Registration Failed: " + authyUser.getError().toString()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendHelp(ProxiedPlayer player) {
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&7Help"));
|
||||
player.sendMessage(Utils.ft("&a/authy help &7- Display this information"));
|
||||
player.sendMessage(Utils.ft("&a/authy verify <token> &7- Verify yourself using your Authy &7<token> (you must be registered)"));
|
||||
player.sendMessage(Utils.ft("&a/authy sendsms &7- If not using Authy app request your verification token to be sent via SMS"));
|
||||
player.sendMessage(Utils.ft("&a/authy register <email> <phone number> <country code> &7- &7Register for verification. " +
|
||||
"Example command: &a/authy register &bme@grandtheftmc.net 5276449341 1"));
|
||||
player.sendMessage(Utils.ft("&a/authy countrycodes &7- List all valid country codes"));
|
||||
}
|
||||
|
||||
public void sendCountryCodes(ProxiedPlayer player) {
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&7Country Codes"));
|
||||
player.sendMessages(
|
||||
"United States of America: 1" ,
|
||||
"Canada: 1" ,
|
||||
"Russia: 7" ,
|
||||
"Netherlands: 31" ,
|
||||
"Belgium: 32" ,
|
||||
"Spain: 34" ,
|
||||
"Italy: 39" ,
|
||||
"United Kingdom: 44" ,
|
||||
"Mexico: 52" ,
|
||||
"Australia: 61" ,
|
||||
"Korea (+South): 82" ,
|
||||
"Korea (+North): gtfo crue"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Lang;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.utils.TabComplete;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
public class FindCommand extends Command {
|
||||
|
||||
public FindCommand() {
|
||||
super("find");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
if (args.length != 1) {
|
||||
s.sendMessage(Utils.ft("&c/find <player>"));
|
||||
return;
|
||||
}
|
||||
|
||||
String target = args[0];
|
||||
if (Bungee.getRedisManager().isPlayerOnline(target) && !Utils.isStaff(target)) {
|
||||
ServerInfo serverInfo = Bungee.getRedisManager().getRedisAPI().getServerFor(Bungee.getRedisManager().getUUIDFromName(target));
|
||||
s.sendMessage(Lang.GTM.ft("&a" + target + " &7was found on server &a" + serverInfo.getName().toUpperCase()));
|
||||
}
|
||||
else {
|
||||
s.sendMessage(Lang.GTM.ft("&a" + target + " &7is not online!"));
|
||||
}
|
||||
}
|
||||
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return TabComplete.onTabComplete(sender, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Lang;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.redisbungee.RedisManager;
|
||||
import net.grandtheftmc.Bungee.redisbungee.data.DataType;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.utils.HelpLog;
|
||||
import net.grandtheftmc.Bungee.utils.TabComplete;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class GlobalMessageCommand extends Command implements TabExecutor {
|
||||
|
||||
public GlobalMessageCommand() {
|
||||
super(
|
||||
"globalmessage",
|
||||
null,
|
||||
"gmsg", "gmessage", "globalmsg", "gtell", "globaltell", "gwhisper", "globalwhisper", "globalw", "gw", "globalchat", "globalc"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
Redis procedure:
|
||||
----------------
|
||||
- Players may reside on different servers across bungee instances.
|
||||
1) Check if name matches, or part matches a player on the current bungee instance.
|
||||
Yes: Send msg directly.
|
||||
No: Go to step 2.
|
||||
2) Check if name matches, or part matches a player across all redis instances.
|
||||
Yes: Send GMSG packet on PubSub redis channel.
|
||||
No: Notify player not found.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
if (args.length < 2) {
|
||||
s.sendMessage(Utils.ft("&c/gmsg <player> <msg>"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(s instanceof ProxiedPlayer)) {
|
||||
s.sendMessage(Utils.ft("&cYou are not a player!"));
|
||||
return;
|
||||
}
|
||||
|
||||
String sender = s.getName();
|
||||
String targetName = null;
|
||||
ProxiedPlayer senderPlayer = (ProxiedPlayer) s;
|
||||
|
||||
if (args[0].equalsIgnoreCase(senderPlayer.getName())) {
|
||||
s.sendMessage(Utils.ft("&cYou cannot message yourself!"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ProxiedPlayer target = null;
|
||||
|
||||
//Try to direct match player name with all players on this proxy instance.
|
||||
if ((target = ProxyServer.getInstance().getPlayer(args[0])) == null) {
|
||||
|
||||
//Prefix tab matching, if they haven't typed the full name we may still find a match
|
||||
String search = args[0].toLowerCase();
|
||||
for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
|
||||
if (player.getName().toLowerCase().startsWith(search)) {
|
||||
target = player;
|
||||
targetName = player.getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (target == null) {
|
||||
//The player we are searching for is not on this bungee instance, try search on redis
|
||||
|
||||
RedisManager mngr = Bungee.getRedisManager();
|
||||
|
||||
//We fail to find a direct match on redis
|
||||
if (!mngr.isPlayerOnline(args[0])) {
|
||||
|
||||
//Try a partial match search
|
||||
for (String redisName : mngr.getRedisAPI().getHumanPlayersOnline()) {
|
||||
if (redisName.startsWith(search)) {
|
||||
targetName = redisName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//the player is online, but on another server so send a pub sub msg.
|
||||
targetName = args[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If the player couldn't be found locally, or via redis let the player know.
|
||||
if (target == null && targetName == null) {
|
||||
Utils.msg(s, "&7That player is not on the server!");
|
||||
return;
|
||||
}
|
||||
|
||||
else if (targetName != null && targetName.equalsIgnoreCase(senderPlayer.getName())) {
|
||||
s.sendMessage(Utils.ft("&cYou cannot message yourself!"));
|
||||
return;
|
||||
}
|
||||
|
||||
else if (target != null && target.getName().equalsIgnoreCase(senderPlayer.getName())) {
|
||||
s.sendMessage(Utils.ft("&cYou cannot message yourself!"));
|
||||
return;
|
||||
}
|
||||
|
||||
//Build the message
|
||||
String msg = "";
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
msg += (i > 1 ? " " : "") + args[i];
|
||||
}
|
||||
|
||||
|
||||
if (target != null) {
|
||||
//player is on same server so we can message them directly
|
||||
//This method is deprecated, but still has use in local instances so this should be reviewed. TODO.
|
||||
String url = "";
|
||||
for (String string : msg.split(" ")) {
|
||||
if (string.matches("^((https?|ftp)://|(www|ftp)\\.)?[a-z0-9-]+(\\.[a-z0-9-]+)+([/?].*)?$")) {
|
||||
url = string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Send GMSG to recipient
|
||||
BaseComponent[] a = new ComponentBuilder(Lang.GMSG.f("&7[" + Utils.getColoredName(senderPlayer) + "&7 -> me] &r" + msg))
|
||||
.event(url.isEmpty() ? new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/gmsg " + sender + " ")
|
||||
: new ClickEvent(ClickEvent.Action.OPEN_URL, url))
|
||||
.create();
|
||||
target.sendMessage(a);
|
||||
|
||||
//Send GMSG to sender
|
||||
a = new ComponentBuilder(Lang.GMSG.f("&7[me&7 -> " + Utils.getColoredName(target) + "&7] &r" + msg))
|
||||
.event(url.isEmpty() ? new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/gmsg " + target.getName() + " ")
|
||||
: new ClickEvent(ClickEvent.Action.OPEN_URL, url))
|
||||
.create();
|
||||
senderPlayer.sendMessage(a);
|
||||
|
||||
//show the player what they said
|
||||
Optional<User> userOptional;
|
||||
if (target == null) {
|
||||
userOptional = Optional.empty();
|
||||
}
|
||||
else {
|
||||
userOptional = Bungee.getUserManager().getLoadedUser(target.getUniqueId());
|
||||
}
|
||||
|
||||
//Color the target name
|
||||
String coloredName;
|
||||
if (userOptional.isPresent()) {
|
||||
coloredName = Utils.f(userOptional.get().getUserRank().getColor() + target.getName());
|
||||
}
|
||||
else {
|
||||
coloredName = "&8" + target.getName();
|
||||
}
|
||||
|
||||
Optional<User> senderOptional = Bungee.getUserManager().getLoadedUser(senderPlayer.getUniqueId());
|
||||
|
||||
//COlor the senders name
|
||||
String coloredSenderName;
|
||||
if (senderOptional.isPresent()) {
|
||||
coloredSenderName = Utils.f(senderOptional.get().getUserRank().getColor() + senderPlayer.getName());
|
||||
}
|
||||
else {
|
||||
coloredSenderName = "&8" + senderPlayer.getName();
|
||||
}
|
||||
|
||||
//send on social spy
|
||||
sendSocialSpy(senderPlayer, coloredSenderName, coloredName, targetName, msg);
|
||||
|
||||
//Check if sender is staff, if so sent help_close if needed, this should now let staff get tokens for local reqs.
|
||||
closeHelp(senderPlayer, target.getName());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
else {
|
||||
//player on another redis bungee instance
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("target", targetName);
|
||||
map.put("sender", senderPlayer.getName());
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(senderPlayer.getUniqueId());
|
||||
String coloredName;
|
||||
if (userOptional.isPresent()) {
|
||||
coloredName = userOptional.get().getUserRank().getColor() + senderPlayer.getName();
|
||||
} else {
|
||||
coloredName = "&8" + sender;
|
||||
}
|
||||
map.put("senderCol", coloredName);
|
||||
map.put("message", msg);
|
||||
String ser = Bungee.getRedisManager().serialize(DataType.GMSG, map);
|
||||
//Send this serialised object to other redis servers for handling...
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
}
|
||||
|
||||
//show the player what they said
|
||||
Optional<User> userOptional;
|
||||
if (targetName == null) {
|
||||
userOptional = Optional.empty();
|
||||
}
|
||||
else {
|
||||
userOptional = Bungee.getUserManager().getLoadedUser(Bungee.getRedisManager().getRedisAPI().getUuidFromName(targetName));
|
||||
}
|
||||
|
||||
String coloredName;
|
||||
if (userOptional.isPresent()) {
|
||||
coloredName = Utils.f(userOptional.get().getUserRank().getColor() + targetName);
|
||||
}
|
||||
else {
|
||||
coloredName = "&8" + targetName;
|
||||
}
|
||||
|
||||
Optional<User> senderOptional = Bungee.getUserManager().getLoadedUser(senderPlayer.getUniqueId());
|
||||
|
||||
String coloredSenderName;
|
||||
if (senderOptional.isPresent()) {
|
||||
coloredSenderName = Utils.f(senderOptional.get().getUserRank().getColor() + senderPlayer.getName());
|
||||
}
|
||||
else {
|
||||
coloredSenderName = "&8" + senderPlayer.getName();
|
||||
}
|
||||
|
||||
String from = Lang.GMSG.f("&7[me -> " + Utils.f(coloredName) + "&7] &r" + msg);
|
||||
|
||||
String url = "";
|
||||
for (String string : msg.split(" ")) {
|
||||
if (string.matches("^((https?|ftp)://|(www|ftp)\\.)?[a-z0-9-]+(\\.[a-z0-9-]+)+([/?].*)?$")) {
|
||||
url = string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Send GMSG to recipient
|
||||
BaseComponent[] a = new ComponentBuilder(Lang.GMSG.f("&7[me &7-> " + Utils.f(coloredName) + "&r&7] &r" + msg))
|
||||
.event(url.isEmpty() ? new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/gmsg " + targetName + " ")
|
||||
: new ClickEvent(ClickEvent.Action.OPEN_URL, url))
|
||||
.create();
|
||||
|
||||
senderPlayer.sendMessage(a);
|
||||
|
||||
sendSocialSpy(senderPlayer, coloredSenderName, coloredName, targetName, msg);
|
||||
|
||||
//Check if sender is staff, if so sent help_close if needed
|
||||
closeHelp(senderPlayer, targetName);
|
||||
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendSocialSpy(ProxiedPlayer senderPlayer, String coloredSenderName, String coloredName, String targetName, String msg){
|
||||
//regardless of where the recipient is we should socialspy this on the staff chat channel
|
||||
String ss = Lang.GSPY.f("&7[" + coloredSenderName + "&7 -> " + coloredName + "&7] &r" + msg);
|
||||
|
||||
Map<String, Object> socialSpySerialized = new HashMap<>();
|
||||
socialSpySerialized.put("message", ss);
|
||||
socialSpySerialized.put("exclude", ChatColor.stripColor(targetName) + "," + senderPlayer.getName());
|
||||
Bungee.getRedisManager().sendMessage(Bungee.getRedisManager().serialize(DataType.SOCIALSPY, socialSpySerialized));
|
||||
}
|
||||
|
||||
private void closeHelp(ProxiedPlayer player, String targetName) {
|
||||
//Check if sender is staff, if so sent help_close if needed
|
||||
if (player.hasPermission("staffchat.use") && HelpLog.helpTicketExists(targetName)) {
|
||||
Optional<User> helperUserOptional = Bungee.getUserManager().getLoadedUser(player.getUniqueId());
|
||||
String helperName = helperUserOptional.isPresent() ? helperUserOptional.get().getColoredName(player) : player.getName();
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("helper", helperName);
|
||||
map.put("helperUUID", player.getUniqueId().toString());
|
||||
map.put("sender", targetName);
|
||||
String ser = Bungee.getRedisManager().serialize(DataType.HELP_CLOSE, map);
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return TabComplete.onTabComplete(sender, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Lang;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.help.data.HelpCategory;
|
||||
import net.grandtheftmc.Bungee.redisbungee.data.DataType;
|
||||
import net.grandtheftmc.Bungee.utils.RequestRateLimiter;
|
||||
import net.grandtheftmc.Bungee.utils.TabComplete;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class HelpCommand extends Command {
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile(".*(?:h.?ck).*", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
//Allow players to still bypass help if the topic for help isn't listed.
|
||||
private HashMap<UUID, Long> bypassHelp = new HashMap<>();
|
||||
|
||||
/*
|
||||
Redis procedure:
|
||||
----------------
|
||||
1) Forward the help request to the staff chat of all staff members across all bungee instances using redis.
|
||||
2) Clicking on the message should allow the staff member to reply by prompting /gmsg <player>...
|
||||
*/
|
||||
|
||||
public HelpCommand() {
|
||||
super("help", null, "helpop", "ask", "question", "howto", "admin", "mod");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
if (!(s instanceof ProxiedPlayer)) {
|
||||
//It doesn't make sense for the console to ask for help.
|
||||
return;
|
||||
}
|
||||
|
||||
ProxiedPlayer player = (ProxiedPlayer) s;
|
||||
|
||||
if (args.length == 0) {
|
||||
player.sendMessage(Lang.HELP.f("&7Try something like this: &a/help how do I use my car?"));
|
||||
//Bungee.getInstance().getHelpCore().getMainHelpMenu().stream().forEach(bc -> player.sendMessage(bc));
|
||||
return;
|
||||
}
|
||||
|
||||
String msg = String.join(" ", args);
|
||||
|
||||
if (args.length == 1) {
|
||||
|
||||
if (args[0].equalsIgnoreCase("reload")) {
|
||||
//reload the configuration
|
||||
if (player.hasPermission("gtm.generic.admin")) {
|
||||
//reload, for this perm only
|
||||
Bungee.getInstance().getHelpCore().reload();
|
||||
player.sendMessage(Utils.f("&aHelp configuration file has been reloaded."));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[0].equalsIgnoreCase("view-null")) {
|
||||
//Workaround to prevent clicking on the last list items
|
||||
return;
|
||||
}
|
||||
|
||||
HelpCategory cat = Bungee.getInstance().getHelpCore().getAssociatedCategory(args[0].toLowerCase());
|
||||
|
||||
if (args[0].equalsIgnoreCase("help")) {
|
||||
//link to main help menu
|
||||
Bungee.getInstance().getHelpCore().getMainHelpMenu().forEach(player::sendMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cat != null) {
|
||||
cat.getDisplay().forEach(player::sendMessage);
|
||||
} else {
|
||||
|
||||
if (msg.split(" ").length <= 1) {
|
||||
player.sendMessage(Lang.HELP.f("&7Only one word? Try to describe your problem more accurately."));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(PATTERN.matcher(msg).find()) {
|
||||
player.sendMessage(new ComponentBuilder(Utils.f(" &c&lWATCHDAWG&8&l> &7Please use &f/report &7<&fplayer&7> <&freason&7>")).create());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
boolean skipCheck = true;
|
||||
|
||||
/*if(bypassHelp.containsKey(player.getUniqueId())){
|
||||
long last = bypassHelp.get(player.getUniqueId());
|
||||
long ms = System.currentTimeMillis() - last;
|
||||
if (ms <= (1000 * 60)) {
|
||||
//if less than a minute ago allow it
|
||||
skipCheck = true;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (skipCheck) {
|
||||
bypassHelp.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
if (!skipCheck) {
|
||||
|
||||
List<HelpCategory> cats = new ArrayList<>();
|
||||
Set<String> existingCats = new HashSet<>();
|
||||
|
||||
//check for matches
|
||||
for (String a : args) {
|
||||
HelpCategory hc = Bungee.getInstance().getHelpCore().getAssociatedCategory(a.toLowerCase());
|
||||
|
||||
if (hc != null && !existingCats.contains(hc.getSectionName())) {
|
||||
cats.add(hc);
|
||||
//prevent duplicates
|
||||
existingCats.add(hc.getSectionName());
|
||||
}
|
||||
}
|
||||
|
||||
if (!cats.isEmpty()) {
|
||||
//Prompt them to review help before pushing to staff.
|
||||
//Your query matches n help topics.
|
||||
// Click on any of these for further information or do /help.
|
||||
//If this still hasnt answered your question click HERE to ask a staff member.
|
||||
ComponentBuilder b = new ComponentBuilder(Bungee.getInstance().getHelpCore().getHelpMatch());
|
||||
|
||||
for (int i = 0; i < cats.size(); i++) {
|
||||
HelpCategory hc = cats.get(i);
|
||||
b.append(hc.getDisplayName()).event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/help " + hc.getSectionName()));
|
||||
|
||||
|
||||
if ((i + 1) != cats.size()) {
|
||||
//comma delimiters
|
||||
b.append(", ").color(ChatColor.WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//add headers
|
||||
Bungee.getInstance().getHelpCore().getHeader().forEach(h -> player.sendMessage(new ComponentBuilder(Utils.f(h)).create()));
|
||||
|
||||
//matching categories
|
||||
player.sendMessage(b.create());
|
||||
|
||||
//generic msg
|
||||
player.sendMessage(new ComponentBuilder(" " + Bungee.getInstance().getHelpCore().getSendHelp()).event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/help " + msg)).create());
|
||||
|
||||
//add footers
|
||||
Bungee.getInstance().getHelpCore().getFooter().forEach(h -> player.sendMessage(new ComponentBuilder(Utils.f(h)).create()));
|
||||
|
||||
bypassHelp.put(player.getUniqueId(), System.currentTimeMillis());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!RequestRateLimiter.requestCmd(player.getUniqueId())) {
|
||||
s.sendMessage(Utils.ft("&cYou have issued this command recently, please wait a second."));
|
||||
return;
|
||||
}
|
||||
|
||||
//broadcast to redis
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("sender", player.getName());
|
||||
map.put("server", player.getServer().getInfo().getName());
|
||||
map.put("message", msg);
|
||||
|
||||
String ser = Bungee.getRedisManager().serialize(DataType.HELP, map);
|
||||
//Send this serialised object to other redis servers for handling...
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
|
||||
player.sendMessage(Lang.HELP.f("&7Your message has been sent to all online staff. Use &a&l\"/gmsg <name>\"&7 to talk to them individually."));
|
||||
|
||||
// log
|
||||
String logMessage = "[HELP] " + player.getName() + ": " + msg;
|
||||
|
||||
Map<String, Object> chatLogSerializd = new HashMap<>();
|
||||
chatLogSerializd.put("type", "help");
|
||||
chatLogSerializd.put("message", logMessage);
|
||||
chatLogSerializd.put("logname", "help");
|
||||
Bungee.getRedisManager().sendMessage(Bungee.getRedisManager().serialize(DataType.LOG, chatLogSerializd));
|
||||
}
|
||||
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return TabComplete.onTabComplete(sender, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.users.UserRank;
|
||||
import net.grandtheftmc.ServerType;
|
||||
import net.grandtheftmc.ServerTypeId;
|
||||
import net.grandtheftmc.jedis.JedisChannel;
|
||||
import net.grandtheftmc.jedis.JedisManager;
|
||||
import net.grandtheftmc.jedis.message.ServerQueueMessage;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class HubCommand extends Command {
|
||||
|
||||
private final JedisManager jedisManager;
|
||||
private final String command;
|
||||
|
||||
public HubCommand(JedisManager jedisManager, String command) {
|
||||
super(command, null);
|
||||
this.jedisManager = jedisManager;
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
if (!(s instanceof ProxiedPlayer)) return;
|
||||
ProxiedPlayer player = (ProxiedPlayer) s;
|
||||
// player.connect(Utils.getRandomHub());
|
||||
ServerInfo info = null;
|
||||
ServerType type = ServerType.GLOBAL;
|
||||
|
||||
int id = -1;
|
||||
if(command.toLowerCase().startsWith("hub")) {
|
||||
type = ServerType.HUB;
|
||||
info = Utils.getRandomHub();
|
||||
id = Integer.parseInt(info.getName().toLowerCase().split("hub")[1]);
|
||||
}
|
||||
|
||||
if(command.toLowerCase().startsWith("vice")) {
|
||||
type = ServerType.VICE;
|
||||
info = Utils.getRandomServer(command);
|
||||
id = Integer.parseInt(info.getName().toLowerCase().split("vice")[1]);
|
||||
}
|
||||
if(command.toLowerCase().startsWith("gtm") || command.toLowerCase().startsWith("gta")) {
|
||||
type = ServerType.GTM;
|
||||
info = Utils.getRandomServer(command);
|
||||
id = Integer.parseInt(info.getName().toLowerCase().split("gtm")[1]);
|
||||
}
|
||||
|
||||
if(id == -1 || info == null || type == ServerType.GLOBAL) {
|
||||
s.sendMessage(Utils.ft("&cServer couldn't be found."));
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<User> user = Bungee.getUserManager().getLoadedUser(player.getUniqueId());
|
||||
UserRank rank = user.map(User::getUserRank).orElse(UserRank.DEFAULT);
|
||||
this.jedisManager.getModule(JedisChannel.SERVER_QUEUE).sendMessage(
|
||||
new ServerQueueMessage(player.getUniqueId(), rank.name(), new ServerTypeId(type, id)),
|
||||
new ServerTypeId(ServerType.OPERATOR, -1)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.redisbungee.data.DataType;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class MotdCommand extends Command {
|
||||
|
||||
public MotdCommand() {
|
||||
super("motd", "motd", "gmotd", "bungeemotd");
|
||||
}
|
||||
|
||||
/*
|
||||
Redis procedure:
|
||||
----------------
|
||||
|
||||
Reload:
|
||||
-------
|
||||
1) Send a pub sub message to all instances to force a reload of the MOTD configurations.
|
||||
|
||||
Set:
|
||||
----
|
||||
1) Send a pub sub message to all instances to set a new MOTD message.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
|
||||
if (args.length == 0) {
|
||||
s.sendMessage(Utils.ft("&7/motd reload"));
|
||||
s.sendMessage(Utils.ft("&7/motd set <msg>"));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args[0]) {
|
||||
|
||||
case "reload":
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("reload", true);
|
||||
map.put("sender", (s instanceof ProxiedPlayer) ? ((ProxiedPlayer) s).getName() : "CONSOLE");
|
||||
|
||||
String ser = Bungee.getRedisManager().serialize(DataType.MOTD, map);
|
||||
//Send this serialised object to other redis servers for handling...
|
||||
//The player/console is notified on the listener end..
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
return;
|
||||
|
||||
case "set":
|
||||
String msg = "";
|
||||
for (int i = 1; i < args.length; i++)
|
||||
msg += args[i] + ' ';
|
||||
if (msg.endsWith(" "))
|
||||
msg = msg.substring(0, msg.length() - 1);
|
||||
|
||||
map = new HashMap<>();
|
||||
map.put("motd", msg);
|
||||
map.put("sender", (s instanceof ProxiedPlayer) ? ((ProxiedPlayer) s).getName() : "CONSOLE");
|
||||
|
||||
ser = Bungee.getRedisManager().serialize(DataType.MOTD, map);
|
||||
//Send this serialised object to other redis servers for handling...
|
||||
//The player/console is notified on the listener end..
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.database.BaseDatabase;
|
||||
import net.grandtheftmc.Bungee.redisbungee.data.DataType;
|
||||
import net.grandtheftmc.Bungee.users.UserRank;
|
||||
import net.grandtheftmc.Bungee.utils.TabComplete;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PermsCommand extends Command {
|
||||
|
||||
public PermsCommand() {
|
||||
super("gperms", "gperms", "gpermissions", "globalperms", "globalpermissions");
|
||||
}
|
||||
|
||||
/*
|
||||
Redis procedure:
|
||||
----------------
|
||||
- Send out a request to reload all configurations
|
||||
- Checking userank, direct database lookup
|
||||
- Perms update <user>
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
if (args.length == 0) {
|
||||
s.sendMessage(Utils.ft("&7/gperms reload"));
|
||||
s.sendMessage(Utils.ft("&7/gperms check <username>"));
|
||||
s.sendMessage(Utils.ft("&7/gperms update <username>"));
|
||||
return;
|
||||
}
|
||||
|
||||
String sender = s instanceof ProxiedPlayer ? s.getName() : "CONSOLE";
|
||||
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "reload":
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("reload", true);
|
||||
map.put("sender", sender);
|
||||
String ser = Bungee.getRedisManager().serialize(DataType.PERMS, map);
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
return;
|
||||
|
||||
case "check":
|
||||
if (args.length != 2) {
|
||||
s.sendMessage(Utils.ft("&7/gperms check <username>"));
|
||||
return;
|
||||
}
|
||||
Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT lastname,userrank FROM users WHERE lastname=?;")) {
|
||||
statement.setString(1, args[1]);
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
if (result.isBeforeFirst()) {
|
||||
if (result.isBeforeFirst()) {
|
||||
result.next();
|
||||
UserRank ur = UserRank.getUserRank(result.getString("userrank"));
|
||||
s.sendMessage(Utils.ft("&7User " + args[1] + " rank: " + ur.getColoredName()));
|
||||
} else {
|
||||
s.sendMessage(Utils.ft("&7The user " + args[1] + " does not exist."));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
return;
|
||||
|
||||
case "update":
|
||||
if (args.length != 2) {
|
||||
s.sendMessage(Utils.ft("&7/gperms update <username>"));
|
||||
return;
|
||||
}
|
||||
|
||||
UUID u = Bungee.getRedisManager().getRedisAPI().getUuidFromName(args[1]);
|
||||
if (u == null || !Bungee.getRedisManager().getRedisAPI().isPlayerOnline(u)) {
|
||||
Utils.msg(s, "&7That player is not online!");
|
||||
return;
|
||||
}
|
||||
|
||||
map = new HashMap<>();
|
||||
map.put("sender", sender);
|
||||
map.put("target", args[1]);
|
||||
ser = Bungee.getRedisManager().serialize(DataType.PERMS, map);
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
return;
|
||||
|
||||
default:
|
||||
s.sendMessage(Utils.ft("&7/gperms reload"));
|
||||
s.sendMessage(Utils.ft("&7/gperms check <username>"));
|
||||
s.sendMessage(Utils.ft("&7/gperms update <username>"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return TabComplete.onTabComplete(sender, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Lang;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.users.UserRank;
|
||||
import net.grandtheftmc.Bungee.utils.PlaytimeManager;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class PlaytimeCommand extends Command {
|
||||
|
||||
public PlaytimeCommand() {
|
||||
super("playtime", "playtime.admin", "playtime");
|
||||
}
|
||||
|
||||
/*
|
||||
MySQL DB:
|
||||
---------
|
||||
Typical Row: <uuid> <username> <session-time> <date-time>
|
||||
|
||||
UUID - UUID of player.
|
||||
Username - Username of player.
|
||||
Session Time - Time, in MS that the player was connected to this proxy.
|
||||
Date Time - System time in MS upon disconnect, used to purge old playtime records.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
if (!(s instanceof ProxiedPlayer)) return;
|
||||
|
||||
ProxiedPlayer player = (ProxiedPlayer) s;
|
||||
|
||||
//Don't allow non-admins to use this command.
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(player.getUniqueId());
|
||||
if (!userOptional.isPresent() || !userOptional.get().isRank(UserRank.ADMIN)) {
|
||||
player.sendMessage(Lang.NOPERM.st());
|
||||
return;
|
||||
}
|
||||
|
||||
Bungee.getUserManager().getSortedUsers().forEach(user -> {
|
||||
PlaytimeManager.lookupPlaytime(player, user.getUsername());
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
//import fr.Alphart.BAT.Utils.EnhancedDateFormat;
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.utils.RequestRateLimiter;
|
||||
import net.grandtheftmc.Bungee.utils.TabComplete;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SeenCommand extends Command {
|
||||
|
||||
// private final EnhancedDateFormat dateFormat = new EnhancedDateFormat(true);
|
||||
|
||||
public SeenCommand() {
|
||||
super("seen", null, "lastonline", "lastlogin");
|
||||
}
|
||||
|
||||
/*
|
||||
Redis procedure:
|
||||
----------------
|
||||
1) Checks if player is on the local instance, if not checks redis distributed.
|
||||
2) If player is not found online we check the database. Again TODO: limitations on frequency of access calls.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
/*if (args.length != 1) {
|
||||
s.sendMessage(Utils.ft("&c/seen <player>"));
|
||||
return;
|
||||
}
|
||||
if (!(s instanceof ProxiedPlayer)) {
|
||||
s.sendMessage(Utils.ft("&cYou are not a player!"));
|
||||
return;
|
||||
}
|
||||
|
||||
UUID sender = ((ProxiedPlayer) s).getUniqueId();
|
||||
String player = args[0];
|
||||
ProxiedPlayer p = ProxyServer.getInstance().getPlayer(player);
|
||||
|
||||
boolean online = p != null || Bungee.getRedisManager().isPlayerOnline(player);
|
||||
|
||||
if (online) {
|
||||
s.sendMessage(Utils.ft("&7The player &a" + (p != null ? p.getName() : args[0]) + "&7 is &aonline&7!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!RequestRateLimiter.requestCmd(sender)) {
|
||||
s.sendMessage(Utils.ft("&cYou have issued this command recently, please wait a second."));
|
||||
return;
|
||||
}
|
||||
|
||||
s.sendMessage(Utils.ft("&7Looking up player &a" + player + "&7 in the database."));
|
||||
ProxyServer.getInstance().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
ResultSet rs = Bungee.getBATSQL().query("select BAT_player,lastlogin from BAT_players where BAT_player='" + player + "';");
|
||||
String name1 = null;
|
||||
Timestamp lastlogin = null;
|
||||
ProxiedPlayer p1 = ProxyServer.getInstance().getPlayer(sender);
|
||||
try {
|
||||
if (rs.isBeforeFirst()) {
|
||||
rs.next();
|
||||
name1 = rs.getString("BAT_player");
|
||||
lastlogin = rs.getTimestamp("lastlogin");
|
||||
}
|
||||
rs.close();
|
||||
} catch (SQLException ignored) {
|
||||
p1.sendMessage(Utils.ft("&7Oops, something went wrong! Please try again."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (p1 == null)
|
||||
return;
|
||||
if (lastlogin == null || name1 == null) {
|
||||
p1.sendMessage(Utils.ft("&7That player is not in the database!"));
|
||||
return;
|
||||
}
|
||||
// p1.sendMessage(Utils.ft("&7The player &a" + name1 + "&7 last logged in &a" + this.dateFormat.format(lastlogin) + "&7!"));
|
||||
|
||||
});*/
|
||||
|
||||
}
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return TabComplete.onTabComplete(sender, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.users.UserRank;
|
||||
import net.grandtheftmc.ServerType;
|
||||
import net.grandtheftmc.ServerTypeId;
|
||||
import net.grandtheftmc.jedis.JedisChannel;
|
||||
import net.grandtheftmc.jedis.JedisManager;
|
||||
import net.grandtheftmc.jedis.message.ServerQueueMessage;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ServerCommand extends Command {
|
||||
|
||||
private final JedisManager jedisManager;
|
||||
private final String command;
|
||||
|
||||
public ServerCommand(String command, JedisManager jedisManager) {
|
||||
super(command);
|
||||
this.command = command;
|
||||
this.jedisManager = jedisManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects the player to the specific Bungee server.
|
||||
* @param s Who executes the command.
|
||||
* @param args The desired server ID to connect to.
|
||||
*/
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
if (!(s instanceof ProxiedPlayer)) return;
|
||||
ProxiedPlayer player = (ProxiedPlayer) s;
|
||||
ServerInfo info = ProxyServer.getInstance().getServerInfo(Bungee.getSettings().getServers().get(this.command));
|
||||
if (info == null) {
|
||||
player.sendMessage(Utils.ft("&cThat server does not exist!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(player.getServer().getInfo().getName().equals(info.getName())) {
|
||||
player.sendMessage(Utils.ft("&cYou're already connected to this server!"));
|
||||
return;
|
||||
}
|
||||
|
||||
int id = -1;
|
||||
ServerType type = ServerType.OPERATOR;
|
||||
if(this.command.toLowerCase().startsWith("hub")) {
|
||||
id = Integer.parseInt(this.command.toLowerCase().split("hub")[1]);
|
||||
type = ServerType.HUB;
|
||||
}
|
||||
|
||||
if(this.command.toLowerCase().startsWith("gtm")) {
|
||||
id = Integer.parseInt(this.command.toLowerCase().split("gtm")[1]);
|
||||
type = ServerType.GTM;
|
||||
}
|
||||
|
||||
if(this.command.toLowerCase().startsWith("vice")) {
|
||||
id = Integer.parseInt(this.command.toLowerCase().split("vice")[1]);
|
||||
type = ServerType.VICE;
|
||||
}
|
||||
|
||||
if(this.command.toLowerCase().startsWith("creative")) {
|
||||
id = Integer.parseInt(this.command.toLowerCase().split("creative")[1]);
|
||||
type = ServerType.CREATIVE;
|
||||
}
|
||||
|
||||
if(type == ServerType.OPERATOR || id == -1) return;
|
||||
|
||||
// player.connect(info);
|
||||
Optional<User> user = Bungee.getUserManager().getLoadedUser(player.getUniqueId());
|
||||
UserRank rank = user.map(User::getUserRank).orElse(UserRank.DEFAULT);
|
||||
this.jedisManager.getModule(JedisChannel.SERVER_QUEUE).sendMessage(
|
||||
new ServerQueueMessage(player.getUniqueId(), rank.name(), new ServerTypeId(type, id)),
|
||||
new ServerTypeId(ServerType.OPERATOR, -1)
|
||||
);
|
||||
}
|
||||
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return ProxyServer.getInstance().getServers().keySet();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package net.grandtheftmc.Bungee.commands;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Lang;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.redisbungee.data.DataType;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.utils.TabComplete;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class StaffChatCommand extends Command {
|
||||
|
||||
public StaffChatCommand() {
|
||||
super("staffchat", "staffchat.use", "sc", "staffc", "schat", "adminchat", "adminc", "ac", "achat");
|
||||
}
|
||||
|
||||
/*
|
||||
Redis procedure:
|
||||
----------------
|
||||
1) Staff chat messages should simply be forwarded to all redis instances.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender s, String[] args) {
|
||||
//Allow to chat in staff chat via console
|
||||
if (!(s instanceof ProxiedPlayer)) {
|
||||
StringBuilder msg = new StringBuilder();
|
||||
for (int i = 0; i < args.length; i++)
|
||||
msg.append(i > 0 ? " " : "").append(args[i]);
|
||||
//broadcast to redis
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("sender", "CONSOLE");
|
||||
map.put("message", msg.toString());
|
||||
|
||||
String ser = Bungee.getRedisManager().serialize(DataType.STAFFCHAT, map);
|
||||
//Send this serialised object to other redis servers for handling...
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ProxiedPlayer player = (ProxiedPlayer) s;
|
||||
//This list only contains staff anyway.
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(player.getUniqueId());
|
||||
userOptional.ifPresent(user -> {
|
||||
if (args.length == 0) {
|
||||
user.toggleStaffChat();
|
||||
s.sendMessage(Lang.STAFF.ft("&7You turned " + (user.getStaffChat() ? "&a&lon" : "&c&loff") + "&7 staff chat!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if ("on".equalsIgnoreCase(args[0])) {
|
||||
user.setStaffChat(true);
|
||||
s.sendMessage(Lang.STAFF.ft("&7You turned &a&lon&7 staff chat!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if ("off".equalsIgnoreCase(args[0])) {
|
||||
user.setStaffChat(false);
|
||||
s.sendMessage(Lang.STAFF.ft("&7You turned &c&loff&7 staff chat!"));
|
||||
return;
|
||||
}
|
||||
|
||||
String msg = "";
|
||||
for (int i = 0; i < args.length; i++)
|
||||
msg = (i > 0 ? " " : "") + args[i];
|
||||
|
||||
//broadcast to redis
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("sender", player.getName());
|
||||
map.put("message", msg);
|
||||
|
||||
String ser = Bungee.getRedisManager().serialize(DataType.STAFFCHAT, map);
|
||||
//Send this serialised object to other redis servers for handling...
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//Autocompleting playing names accross the redis network.
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
return TabComplete.onTabComplete(sender, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package net.grandtheftmc.Bungee.database;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* A generic database handler that acts as a singleton so we can reference it
|
||||
* anywhere.
|
||||
*
|
||||
* @author sbahr
|
||||
*/
|
||||
public class BaseDatabase extends DatabaseHandler {
|
||||
|
||||
/** Singleton instance for this class */
|
||||
private static BaseDatabase instance;
|
||||
|
||||
/**
|
||||
* Private constructor as singleton's cannot be instantiated.
|
||||
*/
|
||||
private BaseDatabase() {
|
||||
// Note: DatabaseHandler doesn't have a constructor for a reason
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton instance of this class.
|
||||
* <p>
|
||||
* This allows you to call {@link #getConnection()}.
|
||||
* </p>
|
||||
*
|
||||
* @return The instance of this database.
|
||||
*/
|
||||
public static BaseDatabase getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new BaseDatabase();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static boolean runCustomQuery(String query) {
|
||||
try (Connection connection = getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
statement.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
package net.grandtheftmc.Bungee.database;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
|
||||
import net.grandtheftmc.Bungee.database.component.Database;
|
||||
import net.grandtheftmc.Bungee.database.component.DatabaseCredentials;
|
||||
|
||||
/**
|
||||
* A generic database handler that holds a HikariCP data source so we can have
|
||||
* multiple database connection.
|
||||
*
|
||||
* Note: This should be init() with either the Plugin/Config path to load
|
||||
* settings, or can be init() with just database credentials, which uses default
|
||||
* HikariCP settings.
|
||||
*
|
||||
* @author sbahr
|
||||
*/
|
||||
public class DatabaseHandler implements Database {
|
||||
|
||||
/** The default MySQL driver */
|
||||
private static final String DEFAULT_MYSQL_DRIVER = "com.mysql.jdbc.Driver";
|
||||
/** The database credentials */
|
||||
private DatabaseCredentials dbCreds;
|
||||
/** Data source connection pool from HikariCP */
|
||||
private HikariDataSource hikariSource = new HikariDataSource();
|
||||
|
||||
// NOTE: HikariCP performs best at fixed pool size, minIdle=maxConns
|
||||
// https://github.com/brettwooldridge/HikariCP
|
||||
|
||||
/** How many minimum idle connections should we always have (2) */
|
||||
protected int minIdle = 2;
|
||||
/** How many max connections should exist in pool (2) */
|
||||
protected int maxPoolSize = 2;
|
||||
/** How long, in millis, we stop waiting for new connection (15 secs) */
|
||||
protected int connectionTimeoutMs = 15 * 1000;
|
||||
/** How long, in millis, before connections timeout (45 secs) */
|
||||
protected int idleTimeoutMs = 45 * 1000;
|
||||
/** How long, in millis, this connection can be alive for (30 mins) */
|
||||
protected int maxLifetimeMs = 30 * 60 * 1000;
|
||||
/** How long, in millis, can a connection be gone from a pool (4 secs) */
|
||||
protected int leakDetectionThresholdMs = 4 * 1000;
|
||||
/** The ping alive query */
|
||||
protected String connectionTestQuery = "SELECT 1";
|
||||
/** Should the connection cache prepared statements */
|
||||
protected boolean cachePreparedStatements = true;
|
||||
/** Number of prepared statements to cache per connection */
|
||||
protected int preparedStatementCache = 250;
|
||||
/** Max number of prepared statements to have */
|
||||
protected int maxPreparedStatementCache = 2048;
|
||||
/** The log writer for Hikari */
|
||||
protected PrintWriter logWriter = new PrintWriter(System.out);
|
||||
|
||||
/**
|
||||
* Initialize the handler with the specified database credentials.
|
||||
* <p>
|
||||
* Sets up the configuration for the connection pool and default settings.
|
||||
* </p>
|
||||
*
|
||||
* @param dbCreds - the credentials for the database
|
||||
* @param driver - the driver class
|
||||
*/
|
||||
public void init(DatabaseCredentials dbCreds, String driver) {
|
||||
this.dbCreds = dbCreds;
|
||||
|
||||
// set the driver name for the connection driver
|
||||
hikariSource.setDriverClassName(driver);
|
||||
|
||||
// assume host/port combo together, or could just be without port
|
||||
String connURL = dbCreds.getHost();
|
||||
|
||||
// if a port is defined
|
||||
if (dbCreds.getPort() > 0) {
|
||||
connURL = dbCreds.getHost() + ":" + dbCreds.getPort();
|
||||
}
|
||||
|
||||
// set the jdbc url, note the character encoding
|
||||
// https://stackoverflow.com/questions/3040597/jdbc-character-encoding
|
||||
hikariSource.setJdbcUrl("jdbc:mysql://" + connURL + "/" + dbCreds.getName() + "?characterEncoding=UTF-8");
|
||||
|
||||
// set user/pass
|
||||
hikariSource.setUsername(dbCreds.getUser());
|
||||
hikariSource.setPassword(dbCreds.getPass());
|
||||
|
||||
/** General conf settings for hikari */
|
||||
// works best when minIdle=maxPoolSize
|
||||
hikariSource.setMinimumIdle(minIdle);
|
||||
hikariSource.setMaximumPoolSize(maxPoolSize);
|
||||
|
||||
// how long to wait, for a new connection
|
||||
hikariSource.setConnectionTimeout(connectionTimeoutMs);
|
||||
// how long before idle connection is destroyed
|
||||
hikariSource.setIdleTimeout(idleTimeoutMs);
|
||||
// how long can a connection exist
|
||||
hikariSource.setMaxLifetime(maxLifetimeMs);
|
||||
// how long connection is away from a pool before saying uh oh
|
||||
hikariSource.setLeakDetectionThreshold(leakDetectionThresholdMs);
|
||||
// test query to confirm alive
|
||||
hikariSource.setConnectionTestQuery(connectionTestQuery);
|
||||
// should we cache prepared statements
|
||||
hikariSource.addDataSourceProperty("cachePrepStmts", "" + cachePreparedStatements);
|
||||
// the size of the prepared statement cache
|
||||
hikariSource.addDataSourceProperty("prepStmtCacheSize", "" + preparedStatementCache);
|
||||
// the maximum cache limit
|
||||
hikariSource.addDataSourceProperty("prepStmtCacheSqlLimit", "" + maxPreparedStatementCache);
|
||||
|
||||
// MUST set log writer
|
||||
try {
|
||||
hikariSource.setLogWriter(new PrintWriter(System.out));
|
||||
}
|
||||
catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the database handler given the credentials.
|
||||
*
|
||||
* @param credentials - the login details to this database
|
||||
*/
|
||||
protected void init(DatabaseCredentials credentials) {
|
||||
this.init(credentials, DEFAULT_MYSQL_DRIVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings for HikariCP from the yaml config and stores them
|
||||
* locally in the object, then initializes the database handler.
|
||||
*/
|
||||
public void init(String host, int port, String dbName, String user, String pass) {
|
||||
//
|
||||
// String host = config.getString(path + ".host", "localhost");
|
||||
// int port = config.getInt(path + ".port", 3306);
|
||||
// String dbName = config.getString(path + ".database", "hyphenical");
|
||||
// String username = config.getString(path + ".user", "user");
|
||||
// String password = config.getString(path + ".password", "pass123");
|
||||
//
|
||||
// // connection stats
|
||||
// int minIdle = config.getInt(path + ".min-idle", 2);
|
||||
// int maxConns = config.getInt(path + ".max-conn", 2);
|
||||
//
|
||||
// // load local fields
|
||||
// this.minIdle = minIdle < 0 ? 1 : minIdle;
|
||||
// this.maxPoolSize = maxConns < 1 ? 1 : maxConns;
|
||||
//
|
||||
// // create database credentials
|
||||
DatabaseCredentials creds = new DatabaseCredentials(host, port, dbName, user, pass);
|
||||
|
||||
// // initialize hikari cp
|
||||
init(creds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close HikariCP connection pool, and all the connections.
|
||||
* <p>
|
||||
* Note: This should be called whenever the plugin turns off!
|
||||
* </p>
|
||||
*/
|
||||
public void close() {
|
||||
if (hikariSource != null && !hikariSource.isClosed()) {
|
||||
hikariSource.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public DatabaseCredentials getCredentials() {
|
||||
return dbCreds;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Connection getConnection() {
|
||||
if (hikariSource != null) {
|
||||
try {
|
||||
Connection conn = hikariSource.getConnection();
|
||||
return conn;
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println("[DatabaseHandler] Unable to grab a connection from the connection pool!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package net.grandtheftmc.Bungee.database.component;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* An interface that represents a database (and it's credentials).
|
||||
*
|
||||
* @author sbahr
|
||||
*/
|
||||
public interface Database {
|
||||
|
||||
/**
|
||||
* Get the credentials for the database.
|
||||
*
|
||||
* @return The credentials for the database.
|
||||
*/
|
||||
DatabaseCredentials getCredentials();
|
||||
|
||||
/**
|
||||
* Get the connection for the database.
|
||||
*
|
||||
* @return The connection for the database.
|
||||
*/
|
||||
Connection getConnection();
|
||||
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package net.grandtheftmc.Bungee.database.component;
|
||||
|
||||
/**
|
||||
* Represents an immutable data object containing information about a connection
|
||||
* to the database.
|
||||
*
|
||||
* @author sbahr
|
||||
*/
|
||||
public class DatabaseCredentials {
|
||||
|
||||
/** The host of the db, ex: example.com */
|
||||
private final String host;
|
||||
/** The port associated, ex: 3306 */
|
||||
private final int port;
|
||||
/** The name of the database to use, ex: test_db */
|
||||
private final String dbName;
|
||||
/** The name of the user that has access to the db, ex: user123 */
|
||||
private final String dbUser;
|
||||
/** The password for the user, ex: pass123 */
|
||||
private final String dbPass;
|
||||
|
||||
/**
|
||||
* Construct a new DatabaseCredentials object.
|
||||
*
|
||||
* @param host - the host of the db, ex: example.com
|
||||
* @param port - the port for the db, ex: 3306
|
||||
* @param dbName - the name of the db to use, ex: test_db
|
||||
* @param dbUser - the user of the db, ex: user123
|
||||
* @param dbPass - the pass for the user, ex: pass123
|
||||
*/
|
||||
public DatabaseCredentials(String host, int port, String dbName, String dbUser, String dbPass) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.dbName = dbName;
|
||||
this.dbUser = dbUser;
|
||||
this.dbPass = dbPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new DatabaseCredentials object.
|
||||
* <p>
|
||||
* The port for the host is not defined as an argument and either should be
|
||||
* supplied in the host argument or use a different constructor. If no port
|
||||
* is defined, we'll use the default port.
|
||||
* </p>
|
||||
*
|
||||
* @param host - the host of the db, ex: example.com
|
||||
* @param dbName - the name of the db to use, ex: test_db
|
||||
* @param dbUser - the user of the db, ex: user123
|
||||
* @param dbPass - the pass for the user, ex: pass123
|
||||
*/
|
||||
public DatabaseCredentials(String host, String dbName, String dbUser, String dbPass) {
|
||||
this(host, -1, dbName, dbUser, dbPass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the host associated with this database credentials.
|
||||
* <p>
|
||||
* The host URL, ex: www.example.com
|
||||
* </p>
|
||||
*
|
||||
* @return The host URL for the database.
|
||||
*/
|
||||
public final String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the port number for the database.
|
||||
* <p>
|
||||
* The port number could be irrelevant if defined in {@link #getHost()}. If
|
||||
* the port number is -1, use the default port.
|
||||
* </p>
|
||||
*
|
||||
* @return The port number for the database.
|
||||
*/
|
||||
public final int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the database that we are using.
|
||||
* <p>
|
||||
* This is the name of the database, as there can be multiple databases
|
||||
* within one database.
|
||||
* </p>
|
||||
*
|
||||
* @return The name of the database we are using.
|
||||
*/
|
||||
public final String getName() {
|
||||
return dbName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the username of the user that has access to the database.
|
||||
*
|
||||
* @return The name for the user that has access to this database.
|
||||
*/
|
||||
public final String getUser() {
|
||||
return dbUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the password of the user that has access to the database.
|
||||
*
|
||||
* @return The password, associated with the user, that has access to this
|
||||
* database.
|
||||
*/
|
||||
public final String getPass() {
|
||||
return dbPass;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
package net.grandtheftmc.Bungee.help;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.help.data.HelpCategory;
|
||||
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.ComponentBuilder;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by Adam on 05/06/2017.
|
||||
*/
|
||||
public class HelpCore {
|
||||
|
||||
/*
|
||||
Sample Data: (Tab to delimit keys for multiple checks)
|
||||
------------------------------------------------------
|
||||
|
||||
help:
|
||||
topic:
|
||||
matches: []
|
||||
help: []
|
||||
subtopic:
|
||||
matches: []
|
||||
help: [] - Can be empty or not, doesn't matter
|
||||
|
||||
Example:
|
||||
--------
|
||||
|
||||
help:
|
||||
Vehicles:
|
||||
matches: vehicle,vehicles
|
||||
help: []
|
||||
Jetpacks:
|
||||
matches:
|
||||
- 'jetpack'
|
||||
- 'jetpacks'
|
||||
help:
|
||||
- 'Jetpacks are cool.'
|
||||
- 'Go buy a Jetpack.'
|
||||
Wingsuits:
|
||||
matches:
|
||||
- 'fly'
|
||||
- 'wingsuit'
|
||||
- 'wingsuits'
|
||||
- 'wings'
|
||||
help:
|
||||
- 'Wingsuits are faster than JetPacks.'
|
||||
- 'Or, are they'
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* A list of all the root categories.
|
||||
*/
|
||||
private List<HelpCategory> rootCategories;
|
||||
|
||||
private List<String> footer;
|
||||
private List<String> header;
|
||||
private String pathString, pathDelim, relatedString, title, cats, helpPath, helpMatch, sendHelp;
|
||||
|
||||
/**
|
||||
* Map match strings to each help category.
|
||||
*/
|
||||
private Map<String, HelpCategory> mappings = new HashMap<>();
|
||||
|
||||
private List<BaseComponent[]> mainHelpMenu;
|
||||
|
||||
/**
|
||||
* Create an instance of the help core, load in all the keywords from a config.
|
||||
*
|
||||
* @param io The config to load the help data from.
|
||||
*/
|
||||
public HelpCore(Configuration io) {
|
||||
load(io);
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
rootCategories.clear();
|
||||
header.clear();
|
||||
footer.clear();
|
||||
mappings.clear();
|
||||
mainHelpMenu = null;
|
||||
|
||||
Bungee.getSettings().setHelpConfig(Utils.loadConfig("help"));
|
||||
load(Bungee.getSettings().getHelpConfiguration());
|
||||
}
|
||||
|
||||
private void load(Configuration io) {
|
||||
|
||||
rootCategories = new ArrayList<>();
|
||||
|
||||
header = io.getStringList("formatting.header");
|
||||
footer = io.getStringList("formatting.footer");
|
||||
pathString = Utils.f(io.getString("formatting.path"));
|
||||
pathDelim = Utils.f(io.getString("formatting.pathdelimiter"));
|
||||
relatedString = Utils.f(io.getString("formatting.related"));
|
||||
title = Utils.f(io.getString("formatting.title"));
|
||||
cats = Utils.f(io.getString("formatting.categories"));
|
||||
helpPath = Utils.f(io.getString("formatting.helppath"));
|
||||
helpMatch = Utils.f(io.getString("formatting.helpmatch"));
|
||||
sendHelp = Utils.f(io.getString("formatting.sendhelp"));
|
||||
|
||||
for (String s : io.getSection("help").getKeys()) {
|
||||
//Each key here is a root category
|
||||
|
||||
HelpCategory rootCategory = new HelpCategory(io.getSection("help." + s), null, s);
|
||||
rootCategories.add(rootCategory);
|
||||
}
|
||||
|
||||
//Now traverse the tree to add all matches
|
||||
for (HelpCategory rootCat : rootCategories) {
|
||||
associateMappings(rootCat);
|
||||
}
|
||||
}
|
||||
|
||||
private void associateMappings(HelpCategory category) {
|
||||
//Associate mappings with this category
|
||||
for (String s : category.getMatches()) {
|
||||
mappings.put(s, category);
|
||||
}
|
||||
|
||||
//Now do the same for all children, recursively...
|
||||
category.getChildren().forEach(this::associateMappings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the help category associated with this search string.
|
||||
*
|
||||
* @param s The string to check for matches.
|
||||
* @return The associated help category.
|
||||
*/
|
||||
public HelpCategory getAssociatedCategory(String s) {
|
||||
return mappings.get(s.toLowerCase());
|
||||
}
|
||||
|
||||
public List<BaseComponent[]> getMainHelpMenu() {
|
||||
if (mainHelpMenu == null) {
|
||||
mainHelpMenu = new ArrayList<>();
|
||||
|
||||
//add headers
|
||||
getHeader().forEach(h -> mainHelpMenu.add(new ComponentBuilder(Utils.f(h)).create()));
|
||||
mainHelpMenu.add(new ComponentBuilder(" " + title).create());
|
||||
|
||||
//related Categories
|
||||
ComponentBuilder builder = new ComponentBuilder(" " + cats);
|
||||
|
||||
for (int i = 0; i < rootCategories.size(); i++) {
|
||||
HelpCategory cat = rootCategories.get(i);
|
||||
builder.append(cat.getDisplayName()).event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/help " + cat.getSectionName()));
|
||||
|
||||
if ((i + 1) != rootCategories.size()) {
|
||||
//comma delimiters
|
||||
builder.append(", ").color(ChatColor.WHITE);
|
||||
}
|
||||
}
|
||||
//add categories
|
||||
mainHelpMenu.add(builder.create());
|
||||
|
||||
//add footers
|
||||
getFooter().forEach(h -> mainHelpMenu.add(new ComponentBuilder(Utils.f(h)).create()));
|
||||
}
|
||||
|
||||
return mainHelpMenu;
|
||||
}
|
||||
|
||||
public List<String> getFooter() {
|
||||
return footer;
|
||||
}
|
||||
|
||||
public List<String> getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public String getPathString() {
|
||||
return pathString;
|
||||
}
|
||||
|
||||
public String getPathDelim() {
|
||||
return pathDelim;
|
||||
}
|
||||
|
||||
public String getRelatedString() {
|
||||
return relatedString;
|
||||
}
|
||||
|
||||
public String getHelpPath() {
|
||||
return helpPath;
|
||||
}
|
||||
|
||||
public String getHelpMatch() {
|
||||
return helpMatch;
|
||||
}
|
||||
|
||||
public String getSendHelp() {
|
||||
return sendHelp;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
package net.grandtheftmc.Bungee.help.data;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
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.ComponentBuilder;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Adam on 05/06/2017.
|
||||
*/
|
||||
public class HelpCategory {
|
||||
|
||||
/**
|
||||
* A name representing this section. Eg: Vehicles.
|
||||
*/
|
||||
private String sectionName;
|
||||
|
||||
/**
|
||||
* The display string to show in the menus.
|
||||
*/
|
||||
private String displayName;
|
||||
|
||||
/**
|
||||
* A list of help categories for this node, to support sub-categories.
|
||||
*/
|
||||
private List<HelpCategory> subCategories = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* All lowercase, any strings in this set will be used to check matches for automated help.
|
||||
*/
|
||||
private String[] matches;
|
||||
|
||||
/**
|
||||
* A list of help messages for this topic.
|
||||
*/
|
||||
private String[] help;
|
||||
|
||||
/**
|
||||
* The parent help category of this child, null if a root.
|
||||
*/
|
||||
private HelpCategory parent;
|
||||
|
||||
/**
|
||||
* A Path representing the relative location of this category.
|
||||
* Like Vehicles > Cars > Lambourghini
|
||||
*/
|
||||
private BaseComponent[] path;
|
||||
|
||||
/**
|
||||
* A list of display components, pre-compiled on first request.
|
||||
*/
|
||||
private List<BaseComponent[]> display;
|
||||
|
||||
public HelpCategory(Configuration section, HelpCategory parent, String name) {
|
||||
//Always pass in the root of whatever config section we are processing.
|
||||
|
||||
this.sectionName = name;
|
||||
this.parent = parent;
|
||||
this.displayName = section.contains("display") ? ChatColor.translateAlternateColorCodes('&', section.getString("display")) : name;
|
||||
|
||||
//Load Help
|
||||
List<String> helpList = section.getStringList("help");
|
||||
help = helpList.toArray(new String[helpList.size()]);
|
||||
|
||||
//Load Matches
|
||||
List<String> helpMatches = section.getStringList("matches");
|
||||
//Ensure all values are lowercase.
|
||||
helpMatches.forEach(m -> m = m.toLowerCase());
|
||||
matches = helpMatches.toArray(new String[helpMatches.size()]);
|
||||
|
||||
//Bungee.getInstance().getLogger().info("Loading category: " + sectionName);
|
||||
//Bungee.getInstance().getLogger().info("Loading related subcategories...");
|
||||
|
||||
//Load SubCategories Recursively
|
||||
for (String s : section.getKeys()) {
|
||||
//Bungee.getInstance().getLogger().info("Key = " + s);
|
||||
if (!s.equalsIgnoreCase("help") && !s.equalsIgnoreCase("matches") && !s.equalsIgnoreCase("display")) {
|
||||
//we have found a sub category
|
||||
//Bungee.getInstance().getLogger().info("Loading subcategory: " + sectionName + "->" + s);
|
||||
HelpCategory cat = new HelpCategory(section.getSection(s), this, s);
|
||||
subCategories.add(cat);
|
||||
}
|
||||
}
|
||||
|
||||
//Bungee.getInstance().getLogger().info("Loading category: " + sectionName + " = COMPLETE");
|
||||
}
|
||||
|
||||
public List<HelpCategory> getChildren() {
|
||||
return subCategories;
|
||||
}
|
||||
|
||||
public String[] getMatches() {
|
||||
return matches;
|
||||
}
|
||||
|
||||
public HelpCategory getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean hasParent() {
|
||||
return parent != null;
|
||||
}
|
||||
|
||||
public String getDisplayName(){
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public String getSectionName() {
|
||||
return sectionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a display list of text components to show to the player.
|
||||
*
|
||||
* @return A list of display components.
|
||||
*/
|
||||
public List<BaseComponent[]> getDisplay() {
|
||||
|
||||
if (display == null) {
|
||||
display = new ArrayList<>();
|
||||
|
||||
//add headers
|
||||
Bungee.getInstance().getHelpCore().getHeader().forEach(h -> display.add(new ComponentBuilder(Utils.f(h)).create()));
|
||||
display.add(getPath());
|
||||
|
||||
//related Categories
|
||||
ComponentBuilder builder = new ComponentBuilder(" " + Bungee.getInstance().getHelpCore().getRelatedString());
|
||||
|
||||
for (int i = 0; i < getChildren().size(); i++) {
|
||||
HelpCategory cat = getChildren().get(i);
|
||||
builder.append(cat.getDisplayName()).event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/help " + cat.getSectionName()));
|
||||
|
||||
if ((i + 1) != getChildren().size()) {
|
||||
//comma delimiters
|
||||
builder.append(", ").color(ChatColor.WHITE);
|
||||
}
|
||||
}
|
||||
//add categories
|
||||
if (!getChildren().isEmpty()) {
|
||||
//only show related categories if there are children
|
||||
display.add(builder.create());
|
||||
}
|
||||
|
||||
//display remaining help
|
||||
if (help != null && help.length > 0) {
|
||||
//Only show help if there's some.
|
||||
for (String s : help) {
|
||||
display.add(new ComponentBuilder(" " + ChatColor.translateAlternateColorCodes('&', s)).create());
|
||||
}
|
||||
}
|
||||
|
||||
//add footer
|
||||
Bungee.getInstance().getHelpCore().getFooter().forEach(h -> display.add(new ComponentBuilder(Utils.f(h)).create()));
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a path display string of the current route for this help category.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public BaseComponent[] getPath() {
|
||||
if (path == null) {
|
||||
//build path
|
||||
List<String> route = new ArrayList<>();
|
||||
List<String> displayRoute = new ArrayList<>();
|
||||
route.add(sectionName);
|
||||
displayRoute.add(displayName);
|
||||
|
||||
HelpCategory currentCat = this;
|
||||
|
||||
while (currentCat.hasParent()) {
|
||||
route.add(currentCat.getParent().getSectionName());
|
||||
displayRoute.add(currentCat.getParent().getDisplayName());
|
||||
currentCat = currentCat.getParent();
|
||||
}
|
||||
|
||||
//Add core help.
|
||||
route.add("Help");
|
||||
displayRoute.add(Bungee.getInstance().getHelpCore().getHelpPath());
|
||||
|
||||
Collections.reverse(route);
|
||||
Collections.reverse(displayRoute);
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
route.stream().forEach(p -> b.append(p).append(" > "));
|
||||
//Trim trailing path markers
|
||||
b.setLength(b.length() - Bungee.getInstance().getHelpCore().getPathDelim().length());
|
||||
|
||||
ComponentBuilder builder = new ComponentBuilder(" " + Bungee.getInstance().getHelpCore().getPathString());
|
||||
for (int i = 0; i < route.size(); i++) {
|
||||
String r = route.get(i);
|
||||
//add displayRoute.get(i)
|
||||
builder.append(displayRoute.get(i));
|
||||
|
||||
if ((i + 1) != route.size()) {
|
||||
//path flow object
|
||||
builder.event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/help " + r));
|
||||
builder.append(Bungee.getInstance().getHelpCore().getPathDelim());
|
||||
} else {
|
||||
//We don't want them to be able to click the last thing, so use this tag to negate it
|
||||
builder.event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/help view-null"));
|
||||
}
|
||||
}
|
||||
|
||||
path = builder.create();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package net.grandtheftmc.Bungee.listeners;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.users.UserRank;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ChatEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class Chat implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onChat(ChatEvent event) {
|
||||
try {
|
||||
if (event.isCancelled() || !(event.getSender() instanceof ProxiedPlayer)) return;
|
||||
ProxiedPlayer player = (ProxiedPlayer) event.getSender();
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(player.getUniqueId());
|
||||
userOptional.ifPresent(user -> {
|
||||
if (!user.isAuthyVerified()) {
|
||||
if (event.isCommand() && event.getMessage().startsWith("/authy")) return;
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (user.isRank(UserRank.HELPOP)) {
|
||||
Utils.redisChatLog(player.getName(), event.getMessage());
|
||||
}
|
||||
|
||||
if (event.isCommand()) return;
|
||||
|
||||
if (player.hasPermission("staffchat.use") && (user.getStaffChat() || event.getMessage().startsWith("#"))) {
|
||||
event.setCancelled(true);
|
||||
String msg = event.getMessage().startsWith("#") ? event.getMessage().substring(1) : event.getMessage();
|
||||
Utils.redisStaffChat(user.getColoredName(player), msg);
|
||||
}
|
||||
});
|
||||
} catch(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package net.grandtheftmc.Bungee.listeners;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.redisbungee.data.DataType;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class Connect implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onConnect(ServerConnectEvent event) {
|
||||
|
||||
// grab event variables
|
||||
ProxiedPlayer player = event.getPlayer();
|
||||
|
||||
// TODO test messages remove
|
||||
System.out.println("target: " + event.getTarget());
|
||||
System.out.println("player server: " + player.getServer());
|
||||
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(player.getUniqueId());
|
||||
userOptional.ifPresent(user -> {
|
||||
user.update();
|
||||
Bungee.getUserManager().setPerms(player, user.getUserRank());
|
||||
|
||||
if (!user.isAuthyVerified() && player.getServer() != null) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("uuid", player.getUniqueId().toString());
|
||||
|
||||
String ser = Bungee.getRedisManager().serialize(DataType.STAFF_JOIN, map);
|
||||
//Send this serialised object to other redis servers for handling...
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
});
|
||||
|
||||
// if the player is currently not on a server
|
||||
if (player.getServer() == null) {
|
||||
|
||||
// NOTE: The below attempted to allow force hosts to connect directly through
|
||||
// This failed because force_default_server in bungee MUST be false to allow
|
||||
// players to use force hosts. However, force_default_server being false means
|
||||
// players will joining without a force hosts will ALWAYS go back to the
|
||||
// server they last connected to
|
||||
|
||||
// if no target
|
||||
if (event.getTarget() == null) {
|
||||
event.setTarget(Utils.getRandomHub());
|
||||
}
|
||||
|
||||
else {
|
||||
// if they are attempting to join ANY hub, pick a random one
|
||||
if (event.getTarget().getName().contains("hub")) {
|
||||
event.setTarget(Utils.getRandomHub());
|
||||
} else {
|
||||
// do nothing, as this should let
|
||||
// the player force host through
|
||||
|
||||
// if case force default fails, set their "rejoin server"
|
||||
// as a random hub
|
||||
player.setReconnectServer(Utils.getRandomHub());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO remove test messages
|
||||
System.out.println("target server after: " + event.getTarget());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package net.grandtheftmc.Bungee.listeners;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.redisbungee.data.DataType;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.utils.HelpLog;
|
||||
import net.grandtheftmc.Bungee.utils.PlaytimeManager;
|
||||
import net.grandtheftmc.Bungee.utils.TimeFormatter;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Disconnect implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onDisconnect(PlayerDisconnectEvent event) {
|
||||
ProxiedPlayer player = event.getPlayer();
|
||||
|
||||
//Stop tracking playtime
|
||||
PlaytimeManager.endSession(player);
|
||||
|
||||
if (HelpLog.helpTicketExists(player.getName())) {
|
||||
//send a close
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("helper", "null");
|
||||
map.put("sender", player.getName());
|
||||
String ser = Bungee.getRedisManager().serialize(DataType.HELP_CLOSE, map);
|
||||
//Send this serialised object to other redis servers for handling...
|
||||
Bungee.getRedisManager().sendMessage(ser);
|
||||
}
|
||||
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(player.getUniqueId());
|
||||
userOptional.ifPresent(user -> {
|
||||
user.setLastQuit(System.currentTimeMillis());
|
||||
Long session = user.getLastQuit() - user.getLastJoin();
|
||||
user.setPlaytime(user.getPlaytime() + session);
|
||||
TimeFormatter timeFormatter = new TimeFormatter(TimeUnit.MILLISECONDS, session);
|
||||
String msg = "[QUIT] played for " + timeFormatter.getHours() +
|
||||
"h " + timeFormatter.getMinutes() + "m " + timeFormatter.getSeconds() + "s";
|
||||
Utils.chatLog(player.getName(), msg);
|
||||
});
|
||||
|
||||
// Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
// try (PreparedStatement statement = Bungee.getSQL().prepareStatement("DELETE FROM user_respack WHERE user=UNHEX(?);")) {
|
||||
// statement.setString(1, player.getUniqueId().toString().replaceAll("-", ""));
|
||||
// statement.execute();
|
||||
// } catch (SQLException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// });
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package net.grandtheftmc.Bungee.listeners;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.md_5.bungee.api.AbstractReconnectHandler;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ServerKickEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Kick implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onServerKick(ServerKickEvent event) {
|
||||
ProxiedPlayer player = event.getPlayer();
|
||||
ProxyServer proxy = Bungee.getInstance().getProxy();
|
||||
ServerInfo kickedFrom;
|
||||
|
||||
if (event.getPlayer().getServer() != null) {
|
||||
kickedFrom = event.getPlayer().getServer().getInfo();
|
||||
}
|
||||
else if (proxy.getReconnectHandler() != null) {
|
||||
kickedFrom = proxy.getReconnectHandler().getServer(event.getPlayer());
|
||||
}
|
||||
else {
|
||||
kickedFrom = AbstractReconnectHandler.getForcedHost(event.getPlayer().getPendingConnection());
|
||||
if (kickedFrom == null)
|
||||
kickedFrom = proxy.getServerInfo(event.getPlayer().getPendingConnection().getListener().getServerPriority().get(0));
|
||||
}
|
||||
|
||||
ServerInfo kickTo = Utils.getRandomHub();
|
||||
if (Objects.equals(kickedFrom, kickTo)) return;
|
||||
event.setCancelled(true);
|
||||
event.setCancelServer(kickTo);
|
||||
player.sendMessage(event.getKickReasonComponent());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package net.grandtheftmc.Bungee.listeners;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.users.UserRank;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.LoginEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Login implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onLogin(LoginEvent event) {
|
||||
UUID uuid = event.getConnection().getUniqueId();
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(uuid);
|
||||
userOptional.ifPresent(user -> {
|
||||
if (!Objects.equals(user.getUsername(), event.getConnection().getName()))
|
||||
user.setUsername(event.getConnection().getName());
|
||||
|
||||
user.setLastJoin(System.currentTimeMillis());
|
||||
|
||||
if (user.isRank(UserRank.BUILDER)) {
|
||||
String address = event.getConnection().getAddress().getAddress().getHostAddress();
|
||||
if (user.getLastIPAddress().equals(address))
|
||||
user.setAuthyVerified(true);
|
||||
|
||||
else {
|
||||
Utils.redisChatLog(user.getUsername(), "logged in with unknown IP address " + address);
|
||||
if (user.getAuthyId() != 0) Bungee.getAuthyManager().sendSMSToken(user.getAuthyId());
|
||||
user.setAuthyVerified(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
event.registerIntent(Bungee.getInstance());
|
||||
ProxyServer.getInstance().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid);
|
||||
if (player != null)
|
||||
Bungee.getUserManager().setPerms(player, userOptional.isPresent() ? userOptional.get().getUserRank() : UserRank.DEFAULT);
|
||||
|
||||
event.completeIntent(Bungee.getInstance());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package net.grandtheftmc.Bungee.listeners;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
public class Ping implements Listener {
|
||||
|
||||
// private static final int[] prez_is_12 = new int[]{420, 69, 6969, 666};
|
||||
|
||||
@EventHandler
|
||||
public void onPing(ProxyPingEvent event) {
|
||||
ServerPing ping = event.getResponse();
|
||||
|
||||
ServerPing.Players players = ping.getPlayers();
|
||||
//Set online players to equal the number on all servers distributed across redis.
|
||||
int online = Bungee.getRedisManager().getRedisAPI().getPlayersOnline().size();
|
||||
players.setOnline(online);
|
||||
//Was here before, but not exactly sure why, guessing you have no max cap?
|
||||
// players.setMax(prez_is_12[ThreadLocalRandom.current().nextInt(0, prez_is_12.length-1)]);
|
||||
players.setMax(1500);
|
||||
|
||||
if (Bungee.getSettings().getMotd() != null) {
|
||||
//Set our MOTD if one exists
|
||||
ping.setDescriptionComponent(Utils.ft(Bungee.getSettings().getMotd()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,258 @@
|
|||
package net.grandtheftmc.Bungee.redisbungee;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Lang;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.database.BaseDatabase;
|
||||
import net.grandtheftmc.Bungee.redisbungee.data.DataType;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.users.UserRank;
|
||||
import net.grandtheftmc.Bungee.utils.HelpLog;
|
||||
import net.grandtheftmc.Bungee.utils.PlaytimeManager;
|
||||
import net.grandtheftmc.Bungee.utils.UUIDUtil;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
public class RedisListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPubSubMessage(PubSubMessageEvent event) {
|
||||
if (event.getChannel().equalsIgnoreCase(Bungee.getRedisManager().getMessageChannel())) {
|
||||
JSONObject serialized = new JSONObject(event.getMessage());
|
||||
|
||||
String dataTypeString = serialized.getString("datatype");
|
||||
DataType typeEnum = DataType.valueOf(dataTypeString);
|
||||
|
||||
if (typeEnum == null) {
|
||||
//Invalid datatype
|
||||
return;
|
||||
}
|
||||
|
||||
DataType dataType = DataType.valueOf(serialized.getString("datatype"));
|
||||
|
||||
switch (dataType) {
|
||||
case GMSG:
|
||||
String target = serialized.getString("target");
|
||||
if (Bungee.getInstance().getProxy().getPlayer(target) == null) return;
|
||||
String sender = serialized.getString("sender");
|
||||
String message = serialized.getString("message");
|
||||
String senderColName = Utils.f(serialized.getString("senderCol"));
|
||||
ProxiedPlayer targetPlayer = Bungee.getInstance().getProxy().getPlayer(target);
|
||||
String url = "";
|
||||
for (String string : message.split(" ")) {
|
||||
if (string.matches("^((https?|ftp)://|(www|ftp)\\.)?[a-z0-9-]+(\\.[a-z0-9-]+)+([/?].*)?$")) {
|
||||
url = string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
BaseComponent[] a = new ComponentBuilder(Lang.GMSG.f("&7[" + senderColName + "&7 -> me] &r" + message))
|
||||
.event(url.isEmpty() ? new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/gmsg " + sender + " ")
|
||||
: new ClickEvent(ClickEvent.Action.OPEN_URL, url))
|
||||
.create();
|
||||
targetPlayer.sendMessage(a);
|
||||
break;
|
||||
|
||||
case STAFFCHAT:
|
||||
//A message has been distributed to the staff chat, send this message to all online staff
|
||||
Utils.staffChat(serialized.getString("sender"), serialized.getString("message"));
|
||||
break;
|
||||
|
||||
case STAFF_JOIN:
|
||||
PlaytimeManager.beginSession(serialized.getString("uuid"));
|
||||
break;
|
||||
|
||||
case HELP_CLOSE:
|
||||
String staffResponseName = serialized.getString("helper");
|
||||
|
||||
String helpRequester = serialized.getString("sender");
|
||||
|
||||
if (staffResponseName.equalsIgnoreCase("null")) {
|
||||
//If a player logs out their ticket is automatically closed.
|
||||
HelpLog.closeHelpTicket(helpRequester);
|
||||
return;
|
||||
}
|
||||
|
||||
String staffResponseUUID = serialized.getString("helperUUID");
|
||||
|
||||
//If no ticket exists skip this part.
|
||||
if (!HelpLog.helpTicketExists(helpRequester)) return;
|
||||
|
||||
boolean receiveTokens = HelpLog.closeHelpTicket(helpRequester);
|
||||
|
||||
ProxiedPlayer pp = Bungee.getInstance().getProxy().getPlayer(UUID.fromString(staffResponseUUID));
|
||||
|
||||
ProxyServer.getInstance().getPlayers()
|
||||
.stream()
|
||||
.filter(player -> player.hasPermission("staffchat.use"))
|
||||
.forEach(player ->
|
||||
player.sendMessage(Lang.HELP.ft(staffResponseName
|
||||
+ " &7answered " + helpRequester)));
|
||||
|
||||
if (pp == null) {
|
||||
Bungee.log(staffResponseUUID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (receiveTokens) {
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(pp.getUniqueId());
|
||||
userOptional.ifPresent(user -> {
|
||||
Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("update users set tokens=tokens+" + 1 + " where uuid=?;")) {
|
||||
statement.setString(1, pp.getUniqueId().toString());
|
||||
statement.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case HELP:
|
||||
String playerName = serialized.getString("sender"),
|
||||
server = serialized.getString("server"),
|
||||
msg = serialized.getString("message");
|
||||
Utils.redisHelp(playerName, msg, server);
|
||||
HelpLog.requestHelp(playerName);
|
||||
break;
|
||||
|
||||
case SOCIALSPY:
|
||||
String mess = Utils.f(serialized.getString("message"));
|
||||
String[] exclude = serialized.getString("exclude").split(",");
|
||||
Set<String> ex = new HashSet<>();
|
||||
Arrays.stream(exclude).forEach(e -> ex.add(e.toLowerCase()));
|
||||
//Stop players receiving social spy msgs if they have been msged or sent the msg
|
||||
|
||||
for (ProxiedPlayer proxP : ProxyServer.getInstance().getPlayers()) {
|
||||
Optional<User> u = Bungee.getUserManager().getLoadedUser(proxP.getUniqueId());
|
||||
if (u.isPresent() && u.get().getSocialSpy()) {
|
||||
//User is non null has has social spy enabled.
|
||||
proxP.sendMessage(mess);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MOTD:
|
||||
sender = serialized.getString("sender");
|
||||
if (serialized.has("reload") && serialized.getBoolean("reload")) {
|
||||
//we want to reload the MOTD from the config.
|
||||
Bungee.getSettings().setMotdConfig(Utils.loadConfig("motd"));
|
||||
Bungee.getSettings().setMotd(Bungee.getSettings().getMotdConfig().getString("motd"));
|
||||
|
||||
if (sender.equals("CONSOLE")) {
|
||||
Bungee.getInstance().getLogger().info("MOTD was reloaded successfully.");
|
||||
} else {
|
||||
pp = Bungee.getInstance().getProxy().getPlayer(sender);
|
||||
|
||||
if (pp == null) return;
|
||||
|
||||
pp.sendMessage(Utils.ft("&7Bungee MOTD reloaded successfully."));
|
||||
}
|
||||
} else if (serialized.has("motd")) {
|
||||
//we want to set a new MOTD, colour codes are translated in the ping event so we dont do that here.
|
||||
String motd = serialized.getString("motd");
|
||||
Bungee.getSettings().setMotd(motd);
|
||||
|
||||
if (sender.equals("CONSOLE")) {
|
||||
Bungee.getInstance().getLogger().info("You have set a temporary MOTD! Note that it will reset to the motd.yml value when Bungee restarts.");
|
||||
Bungee.getInstance().getLogger().info(motd);
|
||||
} else {
|
||||
pp = Bungee.getInstance().getProxy().getPlayer(sender);
|
||||
|
||||
if (pp == null) return;
|
||||
|
||||
pp.sendMessage(Utils.ft("&7You have set a temporary MOTD! Note that it will reset to the motd.yml value when Bungee restarts."));
|
||||
pp.sendMessage(Utils.ft(motd));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PERMS:
|
||||
String issuer = serialized.getString("sender");
|
||||
pp = Bungee.getInstance().getProxy().getPlayer(issuer);
|
||||
|
||||
if (serialized.has("reload") && serialized.getBoolean("reload")) {
|
||||
Bungee.getSettings().setPermsConfig(Utils.loadConfig("perms"));
|
||||
Bungee.getUserManager().loadPerms();
|
||||
|
||||
if (pp != null) {
|
||||
pp.sendMessage(Utils.ft("&7GPerms config reloaded."));
|
||||
} else {
|
||||
Bungee.getInstance().getLogger().info("Perms config reloaded.");
|
||||
}
|
||||
|
||||
} else if (serialized.has("target")) {
|
||||
String targetUser = serialized.getString("target");
|
||||
|
||||
ProxiedPlayer targ = Bungee.getInstance().getProxy().getPlayer(targetUser);
|
||||
|
||||
if (pp != null) {
|
||||
pp.sendMessage(Lang.PERMS.ft("&a" + targetUser + " &aupdated."));
|
||||
} else {
|
||||
Bungee.getInstance().getLogger().info(targ.getDisplayName() + " updated.");
|
||||
}
|
||||
|
||||
if (targ != null) {
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(targ.getUniqueId());
|
||||
if (userOptional.isPresent()) {
|
||||
userOptional.get().update();
|
||||
} else {
|
||||
Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT HEX(UP.uuid) AS uid, UP.rank, U.name FROM user_profile UP, user U WHERE UP.uuid=UNHEX(?) AND UP.uuid=U.uuid;")) {
|
||||
statement.setString(1, targ.getUniqueId().toString().replaceAll("-", ""));
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
while (result.next()) {
|
||||
String username = result.getString("name");
|
||||
UUID uuid = UUIDUtil.createUUID(result.getString("uid")).orElse(null);
|
||||
UserRank ur = UserRank.getUserRank(result.getString("rank"));
|
||||
|
||||
User user = Bungee.getUserManager().getLoadedUsersMap().computeIfAbsent(uuid, User::new);
|
||||
|
||||
user.setUserRank(ur);
|
||||
user.setUsername(username);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LOG:
|
||||
String logType = serialized.getString("type");
|
||||
|
||||
if (logType.equals("staff")) {
|
||||
String logSender = serialized.getString("sender");
|
||||
String logMessage = serialized.getString("message");
|
||||
Utils.chatLog(logSender, logMessage);
|
||||
} else {
|
||||
String logMessage = serialized.getString("message");
|
||||
String logName = serialized.getString("logname");
|
||||
Utils.log(logMessage, logName);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package net.grandtheftmc.Bungee.redisbungee;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
|
||||
import net.grandtheftmc.Bungee.redisbungee.data.DataType;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class RedisManager {
|
||||
private final String messageChannel = "gtm_messages";
|
||||
private final RedisBungeeAPI redisBungeeAPI;
|
||||
|
||||
public RedisManager(RedisBungeeAPI redisBungeeAPI) {
|
||||
this.redisBungeeAPI = redisBungeeAPI;
|
||||
}
|
||||
|
||||
public void sendMessage(String serialized) {
|
||||
this.redisBungeeAPI.sendChannelMessage(this.messageChannel, serialized);
|
||||
}
|
||||
|
||||
public UUID getUUIDFromName(String name) {
|
||||
return this.redisBungeeAPI.getUuidFromName(name, false);
|
||||
}
|
||||
|
||||
public boolean isPlayerOnline(String name) {
|
||||
UUID uuid = getUUIDFromName(name);
|
||||
if (uuid == null) return false;
|
||||
return this.redisBungeeAPI.isPlayerOnline(uuid);
|
||||
}
|
||||
|
||||
public RedisBungeeAPI getRedisAPI() {
|
||||
return this.redisBungeeAPI;
|
||||
}
|
||||
|
||||
public String getMessageChannel() {
|
||||
return this.messageChannel;
|
||||
}
|
||||
|
||||
public String serialize(DataType dataType, Map<String, Object> data) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("datatype", dataType.name());
|
||||
data.keySet().forEach(key -> jsonObject.put(key, data.get(key)));
|
||||
return jsonObject.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package net.grandtheftmc.Bungee.redisbungee.data;
|
||||
|
||||
public enum DataType {
|
||||
|
||||
GMSG("GMSG"), STAFFCHAT("STAFFCHAT"), HELP("HELP"), HELP_CLOSE("HELP_C"), SOCIALSPY("SOCIALSPY"), MOTD("MOTD"),
|
||||
PERMS("PERMS"), STAFF_JOIN("STAFFJOIN"), LOG("LOG");
|
||||
|
||||
private final String identifier;
|
||||
|
||||
DataType(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package net.grandtheftmc.Bungee.tasks;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Lang;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AnnouncerTask {
|
||||
|
||||
public AnnouncerTask() {
|
||||
Bungee.getInstance().getProxy().getScheduler().schedule(Bungee.getInstance(), () -> {
|
||||
int count = 0;
|
||||
|
||||
for (UUID uuid : Bungee.getRedisManager().getRedisAPI().getPlayersOnline()) {
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(uuid);
|
||||
if (userOptional.isPresent()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count <= 1) return;
|
||||
Bungee.getInstance().getProxy().broadcast(Lang.GTM.f("&e&lThere are currently " + count + " staff members online! Need help? Use &a&l/help <your message>"));
|
||||
}, 300, 700, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package net.grandtheftmc.Bungee.tasks;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Lang;
|
||||
import net.grandtheftmc.Bungee.users.UserRank;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AuthyTask {
|
||||
|
||||
public AuthyTask() {
|
||||
Bungee.getInstance().getProxy().getScheduler().schedule(Bungee.getInstance(), () -> {
|
||||
Bungee.getUserManager().getLoadedUsers().forEach(user -> {
|
||||
if (!user.isRank(UserRank.BUILDER)) return;
|
||||
|
||||
ProxiedPlayer player = Bungee.getInstance().getProxy().getPlayer(user.getUUID());
|
||||
if (player == null) return;
|
||||
|
||||
if (!user.isAuthyVerified()) {
|
||||
if (user.getAuthyId() == 0) {
|
||||
player.sendMessage(Lang.VERIFICATION.ft("&7You must register with 2FA &7before &7continuing! " +
|
||||
"&a/authy register <email> <phone number> &a<countrycode> " +
|
||||
"&7Need help? &a/authy help &7or contact a &4&lManager"));
|
||||
}
|
||||
|
||||
else {
|
||||
TextComponent textComponent = Lang.VERIFICATION.ft("&7Please enter your 2 factor authentication &7code before continuing! &a/authy verify <code>");
|
||||
textComponent.setColor(ChatColor.GRAY);
|
||||
player.sendMessage(textComponent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 0, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package net.grandtheftmc.Bungee.tasks;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Lang;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.grandtheftmc.Bungee.utils.PlaytimeManager;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PlaytimePurgeTask {
|
||||
|
||||
public PlaytimePurgeTask() {
|
||||
Bungee.getInstance().getProxy().getScheduler().schedule(Bungee.getInstance(), PlaytimeManager::purgeOldSessions, 0, 1, TimeUnit.DAYS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package net.grandtheftmc.Bungee.tasks;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.utils.ServerStatus;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ServerStatusTask {
|
||||
|
||||
public ServerStatusTask() {
|
||||
Bungee.getInstance().getProxy().getScheduler().schedule(Bungee.getInstance(), () -> Bungee.getInstance().getProxy().getServers().values().forEach(serverInfo -> {
|
||||
try {
|
||||
ServerStatus serverStatus = ServerStatus.getServerStatus(serverInfo);
|
||||
serverStatus.updateStatus();
|
||||
}
|
||||
catch (RejectedExecutionException ignored) {}
|
||||
}), 1, 15, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
package net.grandtheftmc.Bungee.users;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.database.BaseDatabase;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class User {
|
||||
private final UUID uuid;
|
||||
private String username;
|
||||
private UserRank ur;
|
||||
private int authyId = 0;
|
||||
private boolean authyVerified;
|
||||
private String lastIPAddress = "0";
|
||||
|
||||
private boolean staffChat;
|
||||
private boolean socialSpy;
|
||||
private long lastJoin;
|
||||
private long lastQuit;
|
||||
private long playtime;
|
||||
|
||||
public User(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
this.dataCheck();
|
||||
}
|
||||
|
||||
public void dataCheck() {
|
||||
this.update();
|
||||
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("INSERT INTO Authy (uuid,authyId) VALUES (?, ?) ON DUPLICATE KEY UPDATE uuid=?;")) {
|
||||
statement.setString(1, this.uuid.toString());
|
||||
statement.setInt(2, this.authyId);
|
||||
statement.setString(3, this.uuid.toString());
|
||||
|
||||
statement.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public UserRank getUserRank() {
|
||||
return this.ur;
|
||||
}
|
||||
|
||||
public void setUserRank(UserRank ur) {
|
||||
this.ur = ur;
|
||||
}
|
||||
|
||||
public boolean isRank(UserRank userRank) {
|
||||
return userRank == this.ur || this.ur.isHigherThan(userRank);
|
||||
}
|
||||
|
||||
public boolean isSpecial() {
|
||||
return this.ur != UserRank.DEFAULT;
|
||||
}
|
||||
|
||||
public int getAuthyId() {
|
||||
return this.authyId;
|
||||
}
|
||||
|
||||
public void setAuthyId(int authyId) {
|
||||
this.authyId = authyId;
|
||||
|
||||
Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("UPDATE Authy SET authyId=? WHERE uuid=?;")) {
|
||||
statement.setInt(1, this.authyId);
|
||||
statement.setString(2, this.uuid.toString());
|
||||
statement.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isAuthyVerified() {
|
||||
if (!this.isRank(UserRank.BUILDER)) return true;
|
||||
return authyVerified;
|
||||
}
|
||||
|
||||
public void setAuthyVerified(boolean authyVerified) {
|
||||
this.authyVerified = authyVerified;
|
||||
}
|
||||
|
||||
public String getLastIPAddress() {
|
||||
return this.lastIPAddress;
|
||||
}
|
||||
|
||||
public void setLastIPAddress(String lastIPAddress) {
|
||||
this.lastIPAddress = lastIPAddress;
|
||||
|
||||
Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("UPDATE Authy SET lastIPAddress=? WHERE uuid=?;")) {
|
||||
statement.setString(1, this.lastIPAddress);
|
||||
statement.setString(2, this.uuid.toString());
|
||||
statement.execute();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean getStaffChat() {
|
||||
return this.staffChat;
|
||||
}
|
||||
|
||||
public void setStaffChat(boolean b) {
|
||||
this.staffChat = b;
|
||||
}
|
||||
|
||||
public void toggleStaffChat() {
|
||||
this.staffChat = !this.staffChat;
|
||||
}
|
||||
|
||||
public boolean getSocialSpy() {
|
||||
return this.socialSpy;
|
||||
}
|
||||
|
||||
public void setSocialSpy(boolean b) {
|
||||
this.socialSpy = b;
|
||||
}
|
||||
|
||||
public Long getLastJoin() {
|
||||
return this.lastJoin;
|
||||
}
|
||||
|
||||
public void setLastJoin(Long lastJoin) {
|
||||
this.lastJoin = lastJoin;
|
||||
}
|
||||
|
||||
public long getLastQuit() {
|
||||
return this.lastQuit;
|
||||
}
|
||||
|
||||
public void setLastQuit(long lastQuit) {
|
||||
this.lastQuit = lastQuit;
|
||||
}
|
||||
|
||||
public Long getPlaytime() {
|
||||
return this.playtime;
|
||||
}
|
||||
|
||||
public void setPlaytime(Long playtime) {
|
||||
this.playtime = playtime;
|
||||
}
|
||||
|
||||
public String getColoredName(ProxiedPlayer player) {
|
||||
return this.ur.getColor() + (this.ur == UserRank.DEFAULT ? "" : "&l") + player.getName();
|
||||
}
|
||||
|
||||
public String getColoredName() {
|
||||
return this.ur.getColor() + (this.ur == UserRank.DEFAULT ? "" : "&l") + this.username;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT UP.rank, U.name FROM user_profile UP, user U WHERE UP.uuid=UNHEX(?) AND UP.uuid=U.uuid;")) {
|
||||
statement.setString(1, this.uuid.toString().replaceAll("-", ""));
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
if (result.next()) {
|
||||
UserRank ur = UserRank.getUserRank(result.getString("rank"));
|
||||
if (!ur.isHigherThan(UserRank.YOUTUBER)) {
|
||||
Bungee.getUserManager().getLoadedUsers().remove(this);
|
||||
return;
|
||||
}
|
||||
this.ur = ur;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT authyId,lastIPAddress FROM Authy WHERE uuid=? LIMIT 1;")) {
|
||||
statement.setString(1, this.uuid.toString());
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
if (result.next()) {
|
||||
this.authyId = result.getInt("authyId");
|
||||
this.lastIPAddress = result.getString("lastIPAddress");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,327 @@
|
|||
package net.grandtheftmc.Bungee.users;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.database.BaseDatabase;
|
||||
import net.grandtheftmc.Bungee.utils.Callback;
|
||||
import net.grandtheftmc.Bungee.utils.UUIDUtil;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class UserManager {
|
||||
|
||||
private final Map<UUID, User> loadedUsers = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Default set of permissions, loaded from configuration
|
||||
*
|
||||
* @see #loadPerms()
|
||||
*/
|
||||
private final Map<UserRank, List<String>> perms = new HashMap<>();
|
||||
|
||||
public UserManager() {
|
||||
this.loadPerms();
|
||||
this.loadUsers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load permissions ranks from configuration file.
|
||||
*/
|
||||
public void loadPerms() {
|
||||
Configuration c = Bungee.getSettings().getPermsConfig();
|
||||
for (String s : c.getKeys()) {
|
||||
UserRank rank = UserRank.getUserRankOrNull(s);
|
||||
if (rank != null) this.perms.put(rank, c.getStringList(s));
|
||||
}
|
||||
this.setPerms();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a default set of users into redis memory from MySQL storage.
|
||||
* <p>
|
||||
* The default set is of all staff members, additional users are loaded on demand.
|
||||
*/
|
||||
public void loadUsers() {
|
||||
Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
this.step1(connection, obj -> {
|
||||
this.step2(connection, obj);
|
||||
});
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
// try (PreparedStatement statement = connection.prepareStatement("SELECT HEX(uuid) AS uid,rank FROM `user_profile` WHERE rank IN ('builder', 'helpop', 'mod', 'srmod', 'admin', 'dev', 'manager', 'owner');")) {
|
||||
// try (ResultSet result = statement.executeQuery()) {
|
||||
// HashMap<UUID, UserRank> map = Maps.newHashMap();
|
||||
// while (result.next()) {
|
||||
// UUID u = UUIDUtil.createUUID(result.getString("uid")).orElse(null);
|
||||
// if (u == null) continue;
|
||||
// map.put(u, UserRank.getUserRank(result.getString("rank")));
|
||||
// }
|
||||
//
|
||||
// UUID uuid = null;
|
||||
// for (UUID uid : map.keySet()) {
|
||||
// uuid = uid;
|
||||
// try (PreparedStatement statement2 = connection.prepareStatement("SELECT lastname,socialSpy FROM `users` WHERE `uuid`=?;")) {
|
||||
// statement2.setString(1, uid.toString());
|
||||
// try (ResultSet result2 = statement2.executeQuery()) {
|
||||
// if (result2.next()) {
|
||||
// String username = result2.getString("lastname");
|
||||
// boolean socialSpy = result2.getBoolean("socialSpy");
|
||||
//
|
||||
// //Add user key to hashmap.
|
||||
// User user = this.loadedUsers.computeIfAbsent(uid, k -> {
|
||||
// User u = new User(k);
|
||||
// Bungee.getInstance().getLogger().info("Successfully cached user " + u.getUUID());
|
||||
// return u;
|
||||
// });
|
||||
//
|
||||
// //Set ranks and other miscellaneous data.
|
||||
// user.setUserRank(map.get(uid));
|
||||
// user.setSocialSpy(socialSpy);
|
||||
// user.setUsername(username);
|
||||
// }
|
||||
// }
|
||||
// } catch (SQLException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ResultSet rs = Bungee.getSQL().query("SELECT authyId,lastIPAddress FROM Authy WHERE uuid='" + uuid.toString() + "' LIMIT 1;");
|
||||
// Optional<User> user = getLoadedUser(uuid);
|
||||
// if (!user.isPresent()) {
|
||||
// rs.close();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// int authyId = 0;
|
||||
// String ipAddress = "0";
|
||||
// if (rs.next()) {
|
||||
// authyId = rs.getInt("authyId");
|
||||
// ipAddress = rs.getString("lastIPAddress");
|
||||
// }
|
||||
// user.get().setAuthyId(authyId);
|
||||
// user.get().setLastIPAddress(ipAddress);
|
||||
// rs.close();
|
||||
// }
|
||||
// }
|
||||
// } catch (SQLException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
|
||||
// try {
|
||||
// ResultSet resultSet = Bungee.getSQL().query("SELECT HEX(uuid) AS uid,rank FROM `user_profile` WHERE rank IN ('builder', 'helpop', 'mod', 'srmod', 'admin', 'dev', 'manager', 'owner');");
|
||||
// HashMap<UUID, UserRank> map = Maps.newHashMap();
|
||||
// while (resultSet.next()) {
|
||||
// UUID u = UUIDUtil.createUUID(resultSet.getString("uid")).orElse(null);
|
||||
// if (u == null) continue;
|
||||
// map.put(u, UserRank.getUserRank(resultSet.getString("rank")));
|
||||
// }
|
||||
// resultSet.close();
|
||||
|
||||
// UUID uuid = null;
|
||||
// for (UUID uid : map.keySet()) {
|
||||
// uuid = uid;
|
||||
// try (PreparedStatement statement = Bungee.getSQL().prepareStatement("SELECT lastname,socialSpy FROM `users` WHERE `uuid`=?;")) {
|
||||
// statement.setString(1, uid.toString());
|
||||
// try (ResultSet set = statement.executeQuery()) {
|
||||
// if (set.next()) {
|
||||
// String username = set.getString("lastname");
|
||||
// boolean socialSpy = set.getBoolean("socialSpy");
|
||||
//
|
||||
// //Add user key to hashmap.
|
||||
// User user = this.loadedUsers.computeIfAbsent(uid, k -> {
|
||||
// User u = new User(k);
|
||||
// Bungee.getInstance().getLogger().info("Successfully cached user " + u.getUUID());
|
||||
// return u;
|
||||
// });
|
||||
//
|
||||
// //Set ranks and other miscellaneous data.
|
||||
// user.setUserRank(map.get(uid));
|
||||
// user.setSocialSpy(socialSpy);
|
||||
// user.setUsername(username);
|
||||
// }
|
||||
// }
|
||||
// } catch (SQLException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
|
||||
// ResultSet rs = Bungee.getSQL().query("SELECT authyId,lastIPAddress FROM Authy WHERE uuid='" + uuid.toString() + "' LIMIT 1;");
|
||||
// Optional<User> user = getLoadedUser(uuid);
|
||||
// if (!user.isPresent()) {
|
||||
// rs.close();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// int authyId = 0;
|
||||
// String ipAddress = "0";
|
||||
// if (rs.next()) {
|
||||
// authyId = rs.getInt("authyId");
|
||||
// ipAddress = rs.getString("lastIPAddress");
|
||||
// }
|
||||
// user.get().setAuthyId(authyId);
|
||||
// user.get().setLastIPAddress(ipAddress);
|
||||
// rs.close();
|
||||
// } catch (SQLException exception) {
|
||||
// exception.printStackTrace();
|
||||
// }
|
||||
});
|
||||
}
|
||||
|
||||
private void step1(Connection connection, Callback<HashMap<UUID, UserRank>> callback) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT HEX(uuid) AS uid,rank FROM `user_profile` WHERE rank IN ('builder', 'helpop', 'mod', 'srmod', 'admin', 'dev', 'manager', 'owner');")) {
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
HashMap<UUID, UserRank> map = Maps.newHashMap();
|
||||
while (result.next()) {
|
||||
UUID u = UUIDUtil.createUUID(result.getString("uid")).orElse(null);
|
||||
if (u == null) continue;
|
||||
map.put(u, UserRank.getUserRank(result.getString("rank")));
|
||||
}
|
||||
|
||||
callback.call(map);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void step2(Connection connection, HashMap<UUID, UserRank> map) {
|
||||
UUID uuid;
|
||||
for (UUID uid : map.keySet()) {
|
||||
uuid = uid;
|
||||
try (PreparedStatement statement2 = connection.prepareStatement("SELECT lastname,socialSpy FROM `users` WHERE `uuid`=?;")) {
|
||||
statement2.setString(1, uid.toString());
|
||||
try (ResultSet result2 = statement2.executeQuery()) {
|
||||
if (result2.next()) {
|
||||
String username = result2.getString("lastname");
|
||||
boolean socialSpy = result2.getBoolean("socialSpy");
|
||||
|
||||
//Add user key to hashmap.
|
||||
User user = this.loadedUsers.computeIfAbsent(uid, k -> {
|
||||
User u = new User(k);
|
||||
Bungee.getInstance().getLogger().info("Successfully cached user " + u.getUUID());
|
||||
return u;
|
||||
});
|
||||
|
||||
//Set ranks and other miscellaneous data.
|
||||
user.setUserRank(map.get(uid));
|
||||
user.setSocialSpy(socialSpy);
|
||||
user.setUsername(username);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.step3(connection, uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private void step3(Connection connection, UUID uuid) {
|
||||
try (PreparedStatement statement2 = connection.prepareStatement("SELECT authyId,lastIPAddress FROM Authy WHERE uuid='" + uuid.toString() + "' LIMIT 1;")) {
|
||||
try (ResultSet result = statement2.executeQuery()) {
|
||||
Optional<User> user = getLoadedUser(uuid);
|
||||
if (!user.isPresent()) {
|
||||
result.close();
|
||||
return;
|
||||
}
|
||||
|
||||
int authyId = 0;
|
||||
String ipAddress = "0";
|
||||
if (result.next()) {
|
||||
authyId = result.getInt("authyId");
|
||||
ipAddress = result.getString("lastIPAddress");
|
||||
}
|
||||
user.get().setAuthyId(authyId);
|
||||
user.get().setLastIPAddress(ipAddress);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPerms() {
|
||||
for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
|
||||
this.getLoadedUser(player.getUniqueId()).ifPresent(user -> this.setPerms(player, user.getUserRank()));
|
||||
}
|
||||
}
|
||||
|
||||
public void setPerms(ProxiedPlayer player, UserRank rank) {
|
||||
if (rank == null) return;
|
||||
for (String perm : new ArrayList<>(player.getPermissions()))
|
||||
player.setPermission(perm, false);
|
||||
|
||||
for (String perm : this.getPermsAndLower(rank))
|
||||
player.setPermission(perm, true);
|
||||
}
|
||||
|
||||
private List<String> getPermsAndLower(UserRank rank) {
|
||||
List<String> perms = new ArrayList<>();
|
||||
if (rank != null)
|
||||
for (UserRank r : UserRank.values()) {
|
||||
List<String> l = this.perms.get(r);
|
||||
if (l != null && !l.isEmpty())
|
||||
perms.addAll(l);
|
||||
if (r == rank) break;
|
||||
}
|
||||
return perms;
|
||||
}
|
||||
|
||||
public Map<UUID, User> getLoadedUsersMap() {
|
||||
return loadedUsers;
|
||||
}
|
||||
|
||||
public Collection<User> getLoadedUsers() {
|
||||
return this.loadedUsers.values();
|
||||
}
|
||||
|
||||
public List<User> getSortedUsers() {
|
||||
Collection<User> users = Bungee.getUserManager().getLoadedUsers();
|
||||
List<User> userList = new ArrayList<>();
|
||||
for (UserRank userRank : UserRank.values()) {
|
||||
userList.addAll(users.stream().filter(user -> user.getUserRank() == userRank).collect(Collectors.toList()));
|
||||
}
|
||||
return userList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the User object of the player with the specified UUID.
|
||||
*
|
||||
* @param uuid
|
||||
* @return
|
||||
*/
|
||||
public Optional<User> getLoadedUser(UUID uuid) {
|
||||
if (uuid == null) return null;
|
||||
return Optional.ofNullable(this.loadedUsers.get(uuid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the User object of the player with the specified username.
|
||||
*
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
public Optional<User> getLoadedUser(String username) {
|
||||
if (username == null) return null;
|
||||
List<User> users = new ArrayList<>();
|
||||
this.loadedUsers.forEach((uuid, user) -> {
|
||||
if (user.getUsername().equalsIgnoreCase(username)) {
|
||||
users.add(user);
|
||||
return;
|
||||
}
|
||||
});
|
||||
return users.isEmpty() ? Optional.empty() : Optional.of(users.get(0));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package net.grandtheftmc.Bungee.users;
|
||||
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public enum UserRank {
|
||||
|
||||
DEFAULT("&8"), VIP("&6"), PREMIUM("&a"), ELITE("&b"), SPONSOR("&5"), SUPREME("&c"),
|
||||
YOUTUBER("&r"), HELPOP("&d"), MOD("&9"), SRMOD("&9"), BUILDER("&f"), ADMIN("&c"),
|
||||
DEV("&9"), MANAGER("&4"), OWNER("&4");
|
||||
|
||||
private final String color;
|
||||
|
||||
UserRank(String color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public static UserRank[] getUserRanks() {
|
||||
return UserRank.class.getEnumConstants();
|
||||
}
|
||||
|
||||
public static UserRank getUserRank(String name) {
|
||||
if (name == null) return UserRank.DEFAULT;
|
||||
for (UserRank ur : getUserRanks())
|
||||
if (ur.getName().equalsIgnoreCase(name))
|
||||
return ur;
|
||||
return UserRank.DEFAULT;
|
||||
}
|
||||
|
||||
public static UserRank getUserRankOrNull(String name) {
|
||||
if (name == null)
|
||||
return null;
|
||||
for (UserRank ur : getUserRanks())
|
||||
if (ur.getName().equalsIgnoreCase(name))
|
||||
return ur;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static UserRank getUserRankExact(String name) {
|
||||
if (name == null)
|
||||
return null;
|
||||
for (UserRank ur : getUserRanks())
|
||||
if (ur.getName().equalsIgnoreCase(name))
|
||||
return ur;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static UserRank[] getDonorRanks() {
|
||||
return new UserRank[] { VIP, PREMIUM, ELITE, SPONSOR, SUPREME };
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return Utils.f(this.isHigherThan(UserRank.YOUTUBER) ? this.color + ChatColor.BOLD : this.color);
|
||||
}
|
||||
|
||||
public String getColoredName() {
|
||||
return Utils.f(this == UserRank.YOUTUBER ? "&rYOU&4TUBER" : this.color + this.getName());
|
||||
}
|
||||
|
||||
public String getColoredNameBold() {
|
||||
return Utils.f(this == UserRank.YOUTUBER ? "&r&lYOU&4&lTUBER" : this.color + "&l" + this.getName());
|
||||
}
|
||||
|
||||
public String getTabPrefix() {
|
||||
return Utils.f(this == UserRank.YOUTUBER ? "&r&lY&4&lT" : this.color + "&l" + this.getName());
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
if (!Objects.equals(this.getName(), "DEFAULT"))
|
||||
return Utils.f(' ' + this.getColoredNameBold() + "&8&l>");
|
||||
return "";
|
||||
}
|
||||
|
||||
public UserRank getNext() {
|
||||
boolean picknext = false;
|
||||
for (UserRank u : getUserRanks()) {
|
||||
if (picknext)
|
||||
return u;
|
||||
if (Objects.equals(u.getName(), this.getName()))
|
||||
picknext = true;
|
||||
}
|
||||
return UserRank.DEFAULT;
|
||||
}
|
||||
|
||||
public boolean isHigherThan(UserRank rank) {
|
||||
for (UserRank r : getUserRanks())
|
||||
if (r == this)
|
||||
return false;
|
||||
else if (r == rank)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package net.grandtheftmc.Bungee.utils;
|
||||
|
||||
public interface Callback<T> {
|
||||
void call(T obj);
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
package net.grandtheftmc.Bungee.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Created by Adam on 05/06/2017.
|
||||
*/
|
||||
public enum DefaultFontInfo {
|
||||
|
||||
A_UPPER('A', 5),
|
||||
A_LOWER('a', 5),
|
||||
B_UPPER('B', 5),
|
||||
B_LOWER('b', 5),
|
||||
C_UPPER('C', 5),
|
||||
C_LOWER('c', 5),
|
||||
D_UPPER('D', 5),
|
||||
D_LOWER('d', 5),
|
||||
E_UPPER('E', 5),
|
||||
E_LOWER('e', 5),
|
||||
F_UPPER('F', 5),
|
||||
F_LOWER('f', 4),
|
||||
G_UPPER('G', 5),
|
||||
G_LOWER('g', 5),
|
||||
H_UPPER('H', 5),
|
||||
H_LOWER('h', 5),
|
||||
I_UPPER('I', 3),
|
||||
I_LOWER('i', 1),
|
||||
J_UPPER('J', 5),
|
||||
J_LOWER('j', 5),
|
||||
K_UPPER('K', 5),
|
||||
K_LOWER('k', 4),
|
||||
L_UPPER('L', 5),
|
||||
L_LOWER('l', 1),
|
||||
M_UPPER('M', 5),
|
||||
M_LOWER('m', 5),
|
||||
N_UPPER('N', 5),
|
||||
N_LOWER('n', 5),
|
||||
O_UPPER('O', 5),
|
||||
O_LOWER('o', 5),
|
||||
P_UPPER('P', 5),
|
||||
P_LOWER('p', 5),
|
||||
Q_UPPER('Q', 5),
|
||||
Q_LOWER('q', 5),
|
||||
R_UPPER('R', 5),
|
||||
R_LOWER('r', 5),
|
||||
S_UPPER('S', 5),
|
||||
S_LOWER('s', 5),
|
||||
T_UPPER('T', 5),
|
||||
T_LOWER('t', 4),
|
||||
U_UPPER('U', 5),
|
||||
U_LOWER('u', 5),
|
||||
V_UPPER('V', 5),
|
||||
V_LOWER('v', 5),
|
||||
W_UPPER('W', 5),
|
||||
W_LOWER('w', 5),
|
||||
X_UPPER('X', 5),
|
||||
X_LOWER('x', 5),
|
||||
Y_UPPER('Y', 5),
|
||||
Y_LOWER('y', 5),
|
||||
Z_UPPER('Z', 5),
|
||||
Z_LOWER('z', 5),
|
||||
NUM_1('1', 5),
|
||||
NUM_2('2', 5),
|
||||
NUM_3('3', 5),
|
||||
NUM_4('4', 5),
|
||||
NUM_5('5', 5),
|
||||
NUM_6('6', 5),
|
||||
NUM_7('7', 5),
|
||||
NUM_8('8', 5),
|
||||
NUM_9('9', 5),
|
||||
NUM_0('0', 5),
|
||||
EXCLAMATION_POINT('!', 1),
|
||||
AT_SYMBOL('@', 6),
|
||||
NUM_SIGN('#', 5),
|
||||
DOLLAR_SIGN('$', 5),
|
||||
PERCENT('%', 5),
|
||||
UP_ARROW('^', 5),
|
||||
AMPERSAND('&', 5),
|
||||
ASTERISK('*', 5),
|
||||
LEFT_PARENTHESIS('(', 4),
|
||||
RIGHT_PERENTHESIS(')', 4),
|
||||
MINUS('-', 5),
|
||||
UNDERSCORE('_', 5),
|
||||
PLUS_SIGN('+', 5),
|
||||
EQUALS_SIGN('=', 5),
|
||||
LEFT_CURL_BRACE('{', 4),
|
||||
RIGHT_CURL_BRACE('}', 4),
|
||||
LEFT_BRACKET('[', 3),
|
||||
RIGHT_BRACKET(']', 3),
|
||||
COLON(':', 1),
|
||||
SEMI_COLON(';', 1),
|
||||
DOUBLE_QUOTE('"', 3),
|
||||
SINGLE_QUOTE('\'', 1),
|
||||
LEFT_ARROW('<', 4),
|
||||
RIGHT_ARROW('>', 4),
|
||||
QUESTION_MARK('?', 5),
|
||||
SLASH('/', 5),
|
||||
BACK_SLASH('\\', 5),
|
||||
LINE('|', 1),
|
||||
TILDE('~', 5),
|
||||
TICK('`', 2),
|
||||
PERIOD('.', 1),
|
||||
COMMA(',', 1),
|
||||
SPACE(' ', 3),
|
||||
DEFAULT('a', 4);
|
||||
|
||||
private final char character;
|
||||
private final int length;
|
||||
|
||||
DefaultFontInfo(char character, int length) {
|
||||
this.character = character;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public char getCharacter() {
|
||||
return this.character;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return this.length;
|
||||
}
|
||||
|
||||
public int getBoldLength() {
|
||||
if (this == SPACE) return this.length;
|
||||
return this.length + 1;
|
||||
}
|
||||
|
||||
public static DefaultFontInfo getDefaultFontInfo(char c) {
|
||||
Optional<DefaultFontInfo> defaultFontInfo = Arrays.stream(values()).filter(d -> d.character == c).findFirst();
|
||||
return defaultFontInfo.orElse(DEFAULT);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package net.grandtheftmc.Bungee.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Adam on 03/06/2017.
|
||||
*/
|
||||
public class HelpLog {
|
||||
|
||||
//A list of users who have requested help.
|
||||
private static Map<String, Long> helpReqs = new HashMap<>();
|
||||
|
||||
//1 Minutes timeout for receiving tokens.
|
||||
private static final int HELP_TOKENS_TIMEOUT = 1000 * 60 * 1;
|
||||
|
||||
/**
|
||||
* Invoked from RedisListener when a player requests help and this gets forwarded to the staff chat.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public static void requestHelp(String name) {
|
||||
helpReqs.put(name.toLowerCase(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked whenever a staff member messages a player who requested help.
|
||||
*
|
||||
* @param name The name of the player the staff member has gmsg'ed.
|
||||
* @return True if they should receive tokens. Let's set a 15 minute timeout on help requests in order to receive tokens.
|
||||
*/
|
||||
public static boolean closeHelpTicket(String name) {
|
||||
name = name.toLowerCase();
|
||||
if (helpReqs.containsKey(name)) {
|
||||
long t = helpReqs.remove(name);
|
||||
long msElapsed = System.currentTimeMillis() - t;
|
||||
return msElapsed <= HELP_TOKENS_TIMEOUT;
|
||||
}
|
||||
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the target of gmsg has an open help ticket.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static boolean helpTicketExists(String name) {
|
||||
return name != null && helpReqs.containsKey(name.toLowerCase());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package net.grandtheftmc.Bungee.utils;
|
||||
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.grandtheftmc.Bungee.Utils;
|
||||
import net.grandtheftmc.Bungee.database.BaseDatabase;
|
||||
import net.grandtheftmc.Bungee.users.User;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlaytimeManager {
|
||||
|
||||
//How many days to store session history for.
|
||||
private static final int sessionHistoryDays = 7;
|
||||
private static final String tableName = "playtime";
|
||||
//Map UUID -> Millis() At connect time to track session time.
|
||||
private static Map<UUID, Long> sessions = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Mark the beginning of a playtime session for the connecting player.
|
||||
*
|
||||
* @param uuid The player whose playtime we wish to track.
|
||||
*/
|
||||
public static void beginSession(String uuid) {
|
||||
sessions.put(UUID.fromString(uuid), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* End the playtime session, and store the result in the database.
|
||||
*
|
||||
* @param proxiedPlayer The player whose playtime we wish to track.
|
||||
*/
|
||||
public static void endSession(ProxiedPlayer proxiedPlayer) {
|
||||
if (sessions.containsKey(proxiedPlayer.getUniqueId())) {
|
||||
long now = System.currentTimeMillis();
|
||||
long elapsed = now - sessions.remove(proxiedPlayer.getUniqueId());
|
||||
|
||||
Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
String query = "INSERT INTO " + tableName + " (lastname,uuid,sessiontime,sessiondate) VALUES (?, ?, ?, ?);";
|
||||
try (PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
statement.setString(1, proxiedPlayer.getName());
|
||||
statement.setString(2, proxiedPlayer.getUniqueId().toString());
|
||||
statement.setLong(3, elapsed);
|
||||
statement.setLong(4, now);
|
||||
statement.executeUpdate();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will delete any rows in the DB with session dates older than a week.
|
||||
* Call this every 24hr and on startup.
|
||||
*/
|
||||
public static void purgeOldSessions() {
|
||||
Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
long threshold = System.currentTimeMillis() - (1000 * 60 * 60 * 24 * sessionHistoryDays);
|
||||
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("DELETE FROM " + tableName + " WHERE sessionDate<=" + threshold)) {
|
||||
statement.executeUpdate();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the playtime of another user.
|
||||
*
|
||||
* @param p The player issuing the command.
|
||||
* @param target The name of the user to lookup.
|
||||
*/
|
||||
public static void lookupPlaytime(ProxiedPlayer p, String target) {
|
||||
Bungee.getInstance().getProxy().getScheduler().runAsync(Bungee.getInstance(), () -> {
|
||||
|
||||
long threshold = System.currentTimeMillis() - (1000 * 60 * 60 * 24 * sessionHistoryDays);
|
||||
long totalTime = 0;
|
||||
|
||||
try (Connection connection = BaseDatabase.getInstance().getConnection()) {
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT lastname,sessiontime,sessiondate FROM " + tableName + " WHERE lastname='" + target + "' AND sessiondate>" + threshold + ";")) {
|
||||
try (ResultSet result = statement.executeQuery()) {
|
||||
if (result.isBeforeFirst()) {
|
||||
while (result.next()) {
|
||||
totalTime += result.getLong("sessiontime");
|
||||
}
|
||||
|
||||
Optional<User> userOptional = Bungee.getUserManager().getLoadedUser(target);
|
||||
if (!userOptional.isPresent()) return;
|
||||
|
||||
String s = Utils.formatPlaytime(totalTime);
|
||||
p.sendMessage(Utils.f(userOptional.get().getColoredName() + " &7has played for &a" + s + " &7in the last week."));
|
||||
} else {
|
||||
p.sendMessage(Utils.f("&cThe player " + target + " either doesn't exist, or hasn't played in the last week."));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package net.grandtheftmc.Bungee.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by Adam on 05/06/2017.
|
||||
*/
|
||||
public class RequestRateLimiter {
|
||||
|
||||
/*
|
||||
This class serves to limit requests made by staff members to the database.
|
||||
|
||||
No more than 1 execution every second.
|
||||
|
||||
Still allows frequent use, but without spamming.
|
||||
|
||||
Only applies to the /seen, /alt commands
|
||||
*/
|
||||
|
||||
//Store the issuing player and the time of the last command
|
||||
private static Map<UUID, Long> lastReq = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Attempt to make a request to execute a database related command.
|
||||
* @param u The UUID of the player executing the command.
|
||||
* @return A boolean representing whether they have been granted use of said command or not.
|
||||
*/
|
||||
public static boolean requestCmd(UUID u) {
|
||||
long t = System.currentTimeMillis();
|
||||
|
||||
if (!lastReq.containsKey(u)) {
|
||||
lastReq.put(u, t);
|
||||
return true;
|
||||
}
|
||||
|
||||
long last = lastReq.get(u);
|
||||
if (t - last >= 1000) {
|
||||
//if at least 1 second has passed allow the command.
|
||||
lastReq.put(u, t);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package net.grandtheftmc.Bungee.utils;
|
||||
|
||||
import io.netty.util.internal.ConcurrentSet;
|
||||
import net.md_5.bungee.api.Callback;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class ServerStatus implements Callback<ServerPing> {
|
||||
private static final ConcurrentSet<ServerStatus> serverStatuses = new ConcurrentSet<>();
|
||||
private final ServerInfo serverInfo;
|
||||
private boolean online;
|
||||
|
||||
|
||||
public ServerStatus(ServerInfo serverInfo) {
|
||||
this.serverInfo = serverInfo;
|
||||
serverStatuses.add(this);
|
||||
}
|
||||
|
||||
public static ServerStatus getServerStatus(ServerInfo serverInfo) {
|
||||
Set<ServerStatus> tempStatuses = new HashSet<>(serverStatuses);
|
||||
return tempStatuses.stream()
|
||||
.filter(serverStatus -> serverStatus.getServerInfo() == serverInfo)
|
||||
.findFirst().orElse(new ServerStatus(serverInfo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done(ServerPing serverPing, Throwable throwable) {
|
||||
this.online = throwable == null;
|
||||
}
|
||||
|
||||
public void updateStatus() {
|
||||
this.serverInfo.ping(this);
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return this.online;
|
||||
}
|
||||
|
||||
public ServerInfo getServerInfo() {
|
||||
return this.serverInfo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.grandtheftmc.Bungee.utils;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.grandtheftmc.Bungee.Bungee;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Adam on 02/06/2017.
|
||||
*/
|
||||
public class TabComplete {
|
||||
|
||||
/**
|
||||
* Match a list of players to a search string accross the Redis network.
|
||||
* @param sender Who executed the command.
|
||||
* @param args Arguments of player to search
|
||||
* @return A Set<String> of potential matches.
|
||||
*/
|
||||
public static Set<String> onTabComplete(CommandSender sender, String[] args){
|
||||
if (args.length > 2 || args.length == 0)
|
||||
return ImmutableSet.of();
|
||||
|
||||
Set<String> matches = new HashSet<>();
|
||||
|
||||
if (args.length == 1) {
|
||||
String search = args[0].toLowerCase();
|
||||
|
||||
//We search all redis online players for the autocomplete
|
||||
for (String name : Bungee.getRedisManager().getRedisAPI().getHumanPlayersOnline()) {
|
||||
if (name.toLowerCase().startsWith(search)) {
|
||||
matches.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package net.grandtheftmc.Bungee.utils;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TimeFormatter {
|
||||
private final TimeUnit timeUnit;
|
||||
private Long time;
|
||||
|
||||
public TimeFormatter(TimeUnit timeUnit, Long time) {
|
||||
this.timeUnit = timeUnit;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public Long getTime() {
|
||||
return new Long(this.time);
|
||||
}
|
||||
|
||||
public void setTime(Long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public TimeUnit getTimeUnit() {
|
||||
return this.timeUnit;
|
||||
}
|
||||
|
||||
public Long getSeconds() {
|
||||
return this.timeUnit.toSeconds(this.time) - (this.timeUnit.toMinutes(this.time) * 60);
|
||||
}
|
||||
|
||||
public Long getMinutes() {
|
||||
return this.timeUnit.toMinutes(this.time) - (this.timeUnit.toHours(this.time) * 60);
|
||||
}
|
||||
|
||||
public Long getHours() {
|
||||
return this.timeUnit.toHours(this.time) - (this.timeUnit.toDays(this.time) * 24);
|
||||
}
|
||||
|
||||
public Long getDays() {
|
||||
return this.timeUnit.toDays(this.time);
|
||||
}
|
||||
|
||||
public Long getMillis() {
|
||||
return this.timeUnit.toMillis(this.time);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package net.grandtheftmc.Bungee.utils;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created by Stephen
|
||||
*/
|
||||
public class UUIDUtil {
|
||||
|
||||
/**
|
||||
* A {@link Pattern} used to identify and/or split full UUIDs
|
||||
*/
|
||||
private static final Pattern PATTERN_UUID = Pattern.compile("^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$", Pattern.CASE_INSENSITIVE);
|
||||
/**
|
||||
* A {@link Pattern} used to identify and/or split trimmed UUIDs
|
||||
*/
|
||||
private static final Pattern PATTERN_TRIMMED_UUID = Pattern.compile("^([a-z0-9]{8})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{12})$", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
|
||||
/**
|
||||
* Create a UUID safely from a {@link String}.
|
||||
*
|
||||
* @param string The {@link String} to deserialize into an {@link UUID} object.
|
||||
* @return {@link Optional#empty()} if the provided {@link String} is illegal, otherwise an {@link Optional}
|
||||
* containing the deserialized {@link UUID} object.
|
||||
*/
|
||||
public static Optional<UUID> createUUID(String string) {
|
||||
if (string == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
UUID result = null;
|
||||
|
||||
try {
|
||||
// Is it a valid UUID?
|
||||
if (!PATTERN_UUID.matcher(string).matches()) {
|
||||
// Un-trim UUID if it is trimmed
|
||||
Matcher matcher = PATTERN_TRIMMED_UUID.matcher(string);
|
||||
if (matcher.matches()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 1; i <= matcher.groupCount(); i++) {
|
||||
if (i != 1) {
|
||||
sb.append("-");
|
||||
}
|
||||
|
||||
sb.append(matcher.group(i));
|
||||
}
|
||||
|
||||
string = sb.toString();
|
||||
} else {
|
||||
// Invalid UUID
|
||||
string = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (string != null) {
|
||||
result = UUID.fromString(string);
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
// Useless data passed
|
||||
}
|
||||
|
||||
return Optional.ofNullable(result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
name: Bungee
|
||||
main: net.grandtheftmc.Bungee.Bungee
|
||||
version: 1.3
|
||||
author: GTMDevs
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
\.idea/
|
||||
|
||||
target/classes/
|
||||
|
||||
target/
|
||||
|
||||
*.iml
|
|
@ -0,0 +1 @@
|
|||
First commit.
|
|
@ -0,0 +1,165 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
@ -0,0 +1,13 @@
|
|||
Copyright (c) 2008-2009 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,384 @@
|
|||
<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>
|
||||
|
||||
<groupId>com.massivecraft</groupId>
|
||||
<artifactId>Cartels</artifactId>
|
||||
<version>1.7.1</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>Cartels</name>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>vault-repo</id>
|
||||
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>ess-repo</id>
|
||||
<url>http://repo.ess3.net/content/groups/essentials</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>maven.sk89q.com</id>
|
||||
<url>http://maven.sk89q.com/repo/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>repo.mikeprimm.com</id>
|
||||
<url>http://repo.mikeprimm.com/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>playervaults</id>
|
||||
<url>https://ci.drtshock.net/plugin/repository</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>dmulloy2-repo</id>
|
||||
<url>http://repo.dmulloy2.net/nexus/repository/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>nexus-release</id>
|
||||
<url>https://nexus.grandtheftmc.net/content/repositories/releases/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>nexus-release</id>
|
||||
<name>Internal Releases</name>
|
||||
<url>https://nexus.grandtheftmc.net/content/repositories/releases/</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>nexus-snapshot</id>
|
||||
<name>Internal Snapshots</name>
|
||||
<url>https://nexus.grandtheftmc.net/content/repositories/snapshots/</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.12-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>bungeecord-chat</artifactId>
|
||||
<groupId>net.md-5</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<groupId>javax.persistence</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>junit</artifactId>
|
||||
<groupId>junit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.milkbowl.vault</groupId>
|
||||
<artifactId>VaultAPI</artifactId>
|
||||
<version>1.6</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<groupId>org.bukkit</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sk89q</groupId>
|
||||
<artifactId>worldguard</artifactId>
|
||||
<version>6.1.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<groupId>org.bukkit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>bukkit-classloader-check</artifactId>
|
||||
<groupId>com.sk89q.spigot</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>commandbook</artifactId>
|
||||
<groupId>com.sk89q</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>js</artifactId>
|
||||
<groupId>rhino</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>truezip</artifactId>
|
||||
<groupId>de.schlichtherle</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jchronic</artifactId>
|
||||
<groupId>com.sk89q</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>worldedit</artifactId>
|
||||
<groupId>com.sk89q</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sk89q.worldedit</groupId>
|
||||
<artifactId>worldedit-bukkit</artifactId>
|
||||
<version>6.1.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<groupId>org.bukkit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>bukkit-classloader-check</artifactId>
|
||||
<groupId>org.sk89q.bukkit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>dummypermscompat</artifactId>
|
||||
<groupId>com.sk89q</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jchronic</artifactId>
|
||||
<groupId>com.sk89q</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>js</artifactId>
|
||||
<groupId>rhino</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>truezip</artifactId>
|
||||
<groupId>de.schlichtherle</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jlibnoise</artifactId>
|
||||
<groupId>com.sk89q.lib</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>paranamer</artifactId>
|
||||
<groupId>com.thoughtworks.paranamer</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<groupId>org.yaml</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>10.0.1</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>Essentials</artifactId>
|
||||
<version>2.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>EssentialsChat</artifactId>
|
||||
<version>2.13-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<groupId>org.bukkit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>lombok</artifactId>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>Essentials</artifactId>
|
||||
<groupId>net.ess3</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mkremins</groupId>
|
||||
<artifactId>fanciful</artifactId>
|
||||
<version>0.4.0</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dynmap</groupId>
|
||||
<artifactId>dynmap</artifactId>
|
||||
<version>2.0</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<groupId>org.bukkit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>Permissions</artifactId>
|
||||
<groupId>com.nijikokun.bukkit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>bPermissions</artifactId>
|
||||
<groupId>de.bananaco</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>EssentialsGroupManager</artifactId>
|
||||
<groupId>org.anjocaido</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>spoutpluginapi</artifactId>
|
||||
<groupId>org.getspout</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>PermissionsBukkit</artifactId>
|
||||
<groupId>com.platymuus.bukkit.permissions</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>PermissionsEx</artifactId>
|
||||
<groupId>ru.tehkode</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.6.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.grandtheftmc</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>1.0.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.grandtheftmc</groupId>
|
||||
<artifactId>vice</artifactId>
|
||||
<version>1.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>clean package install</defaultGoal>
|
||||
<finalName>${project.name}</finalName>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<filtering>true</filtering>
|
||||
<directory>src/main/resources/</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<!--
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>mkremins:fanciful</include>
|
||||
<include>com.google.code.gson:gson</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
-->
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>mkremins.fanciful</pattern>
|
||||
<shadedPattern>com.massivecraft.factions.shade.mkremins.fanciful</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.google.gson</pattern>
|
||||
<shadedPattern>com.massivecraft.factions.shade.com.google.gson</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- Nexus deploy -->
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.6.8</version>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-deploy</id>
|
||||
<phase>deploy</phase>
|
||||
<goals>
|
||||
<goal>deploy</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<serverId>nexus</serverId>
|
||||
<nexusUrl>https://nexus.grandtheftmc.net/</nexusUrl>
|
||||
<skipStaging>true</skipStaging>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,16 @@
|
|||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||
<id>bin</id>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<files>
|
||||
<file>
|
||||
<source>${project.build.directory}/${artifactId}.jar</source>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<destName>${artifactId}.jar</destName>
|
||||
</file>
|
||||
</files>
|
||||
</assembly>
|
|
@ -0,0 +1,86 @@
|
|||
package com.massivecraft.factions;
|
||||
|
||||
import com.massivecraft.factions.zcore.persist.json.JSONBoard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public abstract class Board {
|
||||
protected static Board instance = getBoardImpl();
|
||||
|
||||
//----------------------------------------------//
|
||||
// Get and Set
|
||||
//----------------------------------------------//
|
||||
public abstract String getIdAt(FLocation flocation);
|
||||
|
||||
private static Board getBoardImpl() {
|
||||
switch (Conf.backEnd) {
|
||||
case JSON:
|
||||
return new JSONBoard();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Board getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public abstract Faction getFactionAt(FLocation flocation);
|
||||
|
||||
public abstract void setIdAt(String id, FLocation flocation);
|
||||
|
||||
public abstract void setFactionAt(Faction faction, FLocation flocation);
|
||||
|
||||
public abstract void removeAt(FLocation flocation);
|
||||
|
||||
public abstract Set<FLocation> getAllClaims(String factionId);
|
||||
|
||||
public abstract Set<FLocation> getAllClaims(Faction faction);
|
||||
|
||||
// anot to be confused with claims, ownership referring to further member-specific ownership of a claim
|
||||
public abstract void clearOwnershipAt(FLocation flocation);
|
||||
|
||||
public abstract void unclaimAll(String factionId);
|
||||
|
||||
// Is this coord NOT completely surrounded by coords claimed by the same faction?
|
||||
// Simpler: Is there any nearby coord with a faction other than the faction here?
|
||||
public abstract boolean isBorderLocation(FLocation flocation);
|
||||
|
||||
// Is this coord connected to any coord claimed by the specified faction?
|
||||
public abstract boolean isConnectedLocation(FLocation flocation, Faction faction);
|
||||
|
||||
public abstract boolean hasFactionWithin(FLocation flocation, Faction faction, int radius);
|
||||
|
||||
//----------------------------------------------//
|
||||
// Cleaner. Remove orphaned foreign keys
|
||||
//----------------------------------------------//
|
||||
|
||||
public abstract void clean();
|
||||
|
||||
//----------------------------------------------//
|
||||
// Coord count
|
||||
//----------------------------------------------//
|
||||
|
||||
public abstract int getFactionCoordCount(String factionId);
|
||||
|
||||
public abstract int getFactionCoordCount(Faction faction);
|
||||
|
||||
public abstract int getFactionCoordCountInWorld(Faction faction, String worldName);
|
||||
|
||||
//----------------------------------------------//
|
||||
// Map generation
|
||||
//----------------------------------------------//
|
||||
|
||||
/**
|
||||
* The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction
|
||||
* of decreasing z
|
||||
*/
|
||||
public abstract ArrayList<String> getMap(Faction faction, FLocation flocation, double inDegrees);
|
||||
|
||||
public abstract void forceSave();
|
||||
|
||||
public abstract void forceSave(boolean sync);
|
||||
|
||||
public abstract boolean load();
|
||||
}
|
|
@ -0,0 +1,467 @@
|
|||
package com.massivecraft.factions;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.massivecraft.factions.integration.dynmap.DynmapStyle;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Conf {
|
||||
|
||||
public static List<String> baseCommandAliases = new ArrayList<String>();
|
||||
public static boolean allowNoSlashCommand = true;
|
||||
|
||||
// Colors
|
||||
public static ChatColor colorMember = ChatColor.GREEN;
|
||||
public static ChatColor colorAlly = ChatColor.LIGHT_PURPLE;
|
||||
public static ChatColor colorTruce = ChatColor.DARK_PURPLE;
|
||||
public static ChatColor colorNeutral = ChatColor.WHITE;
|
||||
public static ChatColor colorEnemy = ChatColor.RED;
|
||||
|
||||
public static ChatColor colorPeaceful = ChatColor.GOLD;
|
||||
public static ChatColor colorWar = ChatColor.DARK_RED;
|
||||
|
||||
// Power
|
||||
public static double powerPlayerMax = 10.0;
|
||||
public static double powerPlayerMin = -10.0;
|
||||
public static double powerPlayerStarting = 0.0;
|
||||
public static double powerPerMinute = 0.2; // Default health rate... it takes 5 min to heal one power
|
||||
public static double powerPerDeath = 4.0; // A death makes you lose 4 power
|
||||
public static boolean powerRegenOffline = false; // does player power regenerate even while they're offline?
|
||||
public static double powerOfflineLossPerDay = 0.0; // players will lose this much power per day offline
|
||||
public static double powerOfflineLossLimit = 0.0; // players will no longer lose power from being offline once their power drops to this amount or less
|
||||
public static double powerFactionMax = 0.0; // if greater than 0, the cap on how much power a faction can have (additional power from players beyond that will act as a "buffer" of sorts)
|
||||
|
||||
public static String prefixAdmin = "[DrugLord] ";//**
|
||||
public static String prefixMod = "[Lieutenant] ";//*
|
||||
|
||||
public static int factionTagLengthMin = 3;
|
||||
public static int factionTagLengthMax = 10;
|
||||
public static boolean factionTagForceUpperCase = false;
|
||||
|
||||
public static boolean newFactionsDefaultOpen = false;
|
||||
|
||||
// when faction membership hits this limit, players will no longer be able to join using /f join; default is 0, no limit
|
||||
public static int factionMemberLimit = 0;
|
||||
|
||||
// what faction ID to start new players in when they first join the server; default is 0, "no faction"
|
||||
public static String newPlayerStartingFactionID = "0";
|
||||
|
||||
public static boolean showMapFactionKey = true;
|
||||
public static boolean showNeutralFactionsOnMap = true;
|
||||
public static boolean showEnemyFactionsOnMap = true;
|
||||
|
||||
// Disallow joining/leaving/kicking while power is negative
|
||||
public static boolean canLeaveWithNegativePower = true;
|
||||
|
||||
// Configuration for faction-only chat
|
||||
public static boolean factionOnlyChat = true;
|
||||
// Configuration on the Faction tag in chat messages.
|
||||
public static boolean chatTagEnabled = true;
|
||||
public static transient boolean chatTagHandledByAnotherPlugin = false;
|
||||
public static boolean chatTagRelationColored = true;
|
||||
public static String chatTagReplaceString = "[CARTEL]";
|
||||
public static String chatTagInsertAfterString = "";
|
||||
public static String chatTagInsertBeforeString = "";
|
||||
public static int chatTagInsertIndex = 0;
|
||||
public static boolean chatTagPadBefore = false;
|
||||
public static boolean chatTagPadAfter = true;
|
||||
public static String chatTagFormat = "%s" + ChatColor.WHITE;
|
||||
public static String factionChatFormat = "%s:" + ChatColor.WHITE + " %s";
|
||||
public static String allianceChatFormat = ChatColor.LIGHT_PURPLE + "%s:" + ChatColor.WHITE + " %s";
|
||||
public static String truceChatFormat = ChatColor.DARK_PURPLE + "%s:" + ChatColor.WHITE + " %s";
|
||||
|
||||
public static boolean broadcastDescriptionChanges = false;
|
||||
public static boolean broadcastTagChanges = false;
|
||||
|
||||
public static double saveToFileEveryXMinutes = 30.0;
|
||||
|
||||
public static double autoLeaveAfterDaysOfInactivity = 10.0;
|
||||
public static double autoLeaveRoutineRunsEveryXMinutes = 5.0;
|
||||
public static int autoLeaveRoutineMaxMillisecondsPerTick = 5; // 1 server tick is roughly 50ms, so default max 10% of a tick
|
||||
public static boolean removePlayerDataWhenBanned = true;
|
||||
public static boolean autoLeaveDeleteFPlayerData = true; // Let them just remove player from Faction.
|
||||
|
||||
public static boolean worldGuardChecking = false;
|
||||
public static boolean worldGuardBuildPriority = false;
|
||||
|
||||
// server logging options
|
||||
public static boolean logFactionCreate = true;
|
||||
public static boolean logFactionDisband = true;
|
||||
public static boolean logFactionJoin = true;
|
||||
public static boolean logFactionKick = true;
|
||||
public static boolean logFactionLeave = true;
|
||||
public static boolean logLandClaims = true;
|
||||
public static boolean logLandUnclaims = true;
|
||||
public static boolean logMoneyTransactions = true;
|
||||
public static boolean logPlayerCommands = true;
|
||||
|
||||
// prevent some potential exploits
|
||||
public static boolean handleExploitObsidianGenerators = true;
|
||||
public static boolean handleExploitEnderPearlClipping = true;
|
||||
public static boolean handleExploitInteractionSpam = true;
|
||||
public static boolean handleExploitTNTWaterlog = false;
|
||||
public static boolean handleExploitLiquidFlow = false;
|
||||
|
||||
public static boolean homesEnabled = true;
|
||||
public static boolean homesMustBeInClaimedTerritory = true;
|
||||
public static boolean homesTeleportToOnDeath = true;
|
||||
public static boolean homesRespawnFromNoPowerLossWorlds = true;
|
||||
public static boolean homesTeleportCommandEnabled = true;
|
||||
public static boolean homesTeleportCommandEssentialsIntegration = true;
|
||||
public static boolean homesTeleportCommandSmokeEffectEnabled = true;
|
||||
public static float homesTeleportCommandSmokeEffectThickness = 3f;
|
||||
public static boolean homesTeleportAllowedFromEnemyTerritory = true;
|
||||
public static boolean homesTeleportAllowedFromDifferentWorld = true;
|
||||
public static double homesTeleportAllowedEnemyDistance = 32.0;
|
||||
public static boolean homesTeleportIgnoreEnemiesIfInOwnTerritory = true;
|
||||
|
||||
public static boolean disablePVPBetweenNeutralFactions = false;
|
||||
public static boolean disablePVPForFactionlessPlayers = false;
|
||||
public static boolean enablePVPAgainstFactionlessInAttackersLand = false;
|
||||
|
||||
public static int noPVPDamageToOthersForXSecondsAfterLogin = 3;
|
||||
|
||||
public static boolean peacefulTerritoryDisablePVP = true;
|
||||
public static boolean peacefulTerritoryDisableMonsters = false;
|
||||
public static boolean peacefulTerritoryDisableBoom = false;
|
||||
public static boolean peacefulMembersDisablePowerLoss = true;
|
||||
|
||||
public static boolean permanentFactionsDisableLeaderPromotion = false;
|
||||
|
||||
public static boolean claimsMustBeConnected = false;
|
||||
public static boolean claimsCanBeUnconnectedIfOwnedByOtherFaction = true;
|
||||
public static int claimsRequireMinFactionMembers = 1;
|
||||
public static int claimedLandsMax = 0;
|
||||
public static int lineClaimLimit = 5;
|
||||
|
||||
// if someone is doing a radius claim and the process fails to claim land this many times in a row, it will exit
|
||||
public static int radiusClaimFailureLimit = 9;
|
||||
|
||||
public static double considerFactionsReallyOfflineAfterXMinutes = 0.0;
|
||||
|
||||
public static int actionDeniedPainAmount = 1;
|
||||
|
||||
// commands which will be prevented if the player is a member of a permanent faction
|
||||
public static Set<String> permanentFactionMemberDenyCommands = new LinkedHashSet<String>();
|
||||
|
||||
// commands which will be prevented when in claimed territory of another faction
|
||||
public static Set<String> territoryNeutralDenyCommands = new LinkedHashSet<String>();
|
||||
public static Set<String> territoryEnemyDenyCommands = new LinkedHashSet<String>();
|
||||
public static Set<String> territoryAllyDenyCommands = new LinkedHashSet<String>();
|
||||
public static Set<String> warzoneDenyCommands = new LinkedHashSet<String>();
|
||||
public static Set<String> wildernessDenyCommands = new LinkedHashSet<String>();
|
||||
|
||||
public static boolean territoryDenyBuild = true;
|
||||
public static boolean territoryDenyBuildWhenOffline = true;
|
||||
public static boolean territoryPainBuild = false;
|
||||
public static boolean territoryPainBuildWhenOffline = false;
|
||||
public static boolean territoryDenyUseage = true;
|
||||
public static boolean territoryEnemyDenyBuild = true;
|
||||
public static boolean territoryEnemyDenyBuildWhenOffline = true;
|
||||
public static boolean territoryEnemyPainBuild = false;
|
||||
public static boolean territoryEnemyPainBuildWhenOffline = false;
|
||||
public static boolean territoryEnemyDenyUseage = true;
|
||||
public static boolean territoryEnemyProtectMaterials = true;
|
||||
public static boolean territoryAllyDenyBuild = true;
|
||||
public static boolean territoryAllyDenyBuildWhenOffline = true;
|
||||
public static boolean territoryAllyPainBuild = false;
|
||||
public static boolean territoryAllyPainBuildWhenOffline = false;
|
||||
public static boolean territoryAllyDenyUseage = true;
|
||||
public static boolean territoryAllyProtectMaterials = true;
|
||||
public static boolean territoryTruceDenyBuild = true;
|
||||
public static boolean territoryTruceDenyBuildWhenOffline = true;
|
||||
public static boolean territoryTrucePainBuild = false;
|
||||
public static boolean territoryTrucePainBuildWhenOffline = false;
|
||||
public static boolean territoryTruceDenyUseage = true;
|
||||
public static boolean territoryTruceProtectMaterials = true;
|
||||
public static boolean territoryBlockCreepers = false;
|
||||
public static boolean territoryBlockCreepersWhenOffline = false;
|
||||
public static boolean territoryBlockFireballs = false;
|
||||
public static boolean territoryBlockFireballsWhenOffline = false;
|
||||
public static boolean territoryBlockTNT = false;
|
||||
public static boolean territoryBlockTNTWhenOffline = false;
|
||||
public static boolean territoryDenyEndermanBlocks = true;
|
||||
public static boolean territoryDenyEndermanBlocksWhenOffline = true;
|
||||
|
||||
public static boolean safeZoneDenyBuild = true;
|
||||
public static boolean safeZoneDenyUseage = true;
|
||||
public static boolean safeZoneBlockTNT = true;
|
||||
public static boolean safeZonePreventAllDamageToPlayers = false;
|
||||
public static boolean safeZoneDenyEndermanBlocks = true;
|
||||
|
||||
public static boolean warZoneDenyBuild = true;
|
||||
public static boolean warZoneDenyUseage = true;
|
||||
public static boolean warZoneBlockCreepers = false;
|
||||
public static boolean warZoneBlockFireballs = false;
|
||||
public static boolean warZoneBlockTNT = true;
|
||||
public static boolean warZonePowerLoss = true;
|
||||
public static boolean warZoneFriendlyFire = false;
|
||||
public static boolean warZoneDenyEndermanBlocks = true;
|
||||
|
||||
public static boolean wildernessDenyBuild = false;
|
||||
public static boolean wildernessDenyUseage = false;
|
||||
public static boolean wildernessBlockCreepers = false;
|
||||
public static boolean wildernessBlockFireballs = false;
|
||||
public static boolean wildernessBlockTNT = false;
|
||||
public static boolean wildernessPowerLoss = true;
|
||||
public static boolean wildernessDenyEndermanBlocks = false;
|
||||
|
||||
// for claimed areas where further faction-member ownership can be defined
|
||||
public static boolean ownedAreasEnabled = true;
|
||||
public static int ownedAreasLimitPerFaction = 0;
|
||||
public static boolean ownedAreasModeratorsCanSet = false;
|
||||
public static boolean ownedAreaModeratorsBypass = true;
|
||||
public static boolean ownedAreaDenyBuild = true;
|
||||
public static boolean ownedAreaPainBuild = false;
|
||||
public static boolean ownedAreaProtectMaterials = true;
|
||||
public static boolean ownedAreaDenyUseage = true;
|
||||
|
||||
public static boolean ownedMessageOnBorder = true;
|
||||
public static boolean ownedMessageInsideTerritory = true;
|
||||
public static boolean ownedMessageByChunk = false;
|
||||
|
||||
public static boolean pistonProtectionThroughDenyBuild = true;
|
||||
|
||||
public static Set<Material> territoryProtectedMaterials = EnumSet.noneOf(Material.class);
|
||||
public static Set<Material> territoryDenyUseageMaterials = EnumSet.noneOf(Material.class);
|
||||
public static Set<Material> territoryProtectedMaterialsWhenOffline = EnumSet.noneOf(Material.class);
|
||||
public static Set<Material> territoryDenyUseageMaterialsWhenOffline = EnumSet.noneOf(Material.class);
|
||||
|
||||
public static transient Set<EntityType> safeZoneNerfedCreatureTypes = EnumSet.noneOf(EntityType.class);
|
||||
// Economy settings
|
||||
public static boolean econEnabled = true;
|
||||
public static String econUniverseAccount = "";
|
||||
public static double econCostClaimWilderness = 50000.0;//30.0
|
||||
public static double econCostClaimFromFactionBonus = 0.0;//30.0
|
||||
public static double econOverclaimRewardMultiplier = 0.0;
|
||||
public static double econClaimAdditionalMultiplier = 0.05;//0.5
|
||||
public static double econClaimRefundMultiplier = 0.0;//0.7
|
||||
public static double econClaimUnconnectedFee = 0.0;
|
||||
public static double econCostCreate = 1000000.0;//100.0
|
||||
public static double econCostOwner = 0.0;//15.0
|
||||
public static double econCostSethome = 100000.0;//30.0
|
||||
public static double econCostJoin = 0.0;
|
||||
public static double econCostLeave = 0.0;
|
||||
public static double econCostKick = 0.0;
|
||||
public static double econCostInvite = 50000.0;
|
||||
public static double econCostHome = 0.0;
|
||||
public static double econCostTag = 100000.0;
|
||||
public static double econCostDesc = 0.0;
|
||||
public static double econCostTitle = 0.0;
|
||||
public static double econCostList = 0.0;
|
||||
public static double econCostMap = 0.0;
|
||||
public static double econCostPower = 0.0;
|
||||
public static double econCostShow = 0.0;
|
||||
public static double econCostStuck = 0.0;
|
||||
public static double econCostOpen = 0.0;
|
||||
public static double econCostAlly = 0.0;
|
||||
public static double econCostTruce = 0.0;
|
||||
public static double econCostEnemy = 0.0;
|
||||
public static double econCostNeutral = 0.0;
|
||||
public static double econCostNoBoom = 0.0;
|
||||
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INTEGRATION: DYNMAP
|
||||
// -------------------------------------------- //
|
||||
|
||||
// Should the dynmap intagration be used?
|
||||
public static boolean dynmapUse = false;
|
||||
|
||||
// Name of the Factions layer
|
||||
public static String dynmapLayerName = "Factions";
|
||||
|
||||
// Should the layer be visible per default
|
||||
public static boolean dynmapLayerVisible = true;
|
||||
|
||||
// Ordering priority in layer menu (low goes before high - default is 0)
|
||||
public static int dynmapLayerPriority = 2;
|
||||
|
||||
// (optional) set minimum zoom level before layer is visible (0 = default, always visible)
|
||||
public static int dynmapLayerMinimumZoom = 0;
|
||||
|
||||
// Format for popup - substitute values for macros
|
||||
public static String dynmapDescription =
|
||||
"<div class=\"infowindow\">\n"
|
||||
+ "<span style=\"font-weight: bold; font-size: 150%;\">%name%</span><br>\n"
|
||||
+ "<span style=\"font-style: italic; font-size: 110%;\">%description%</span><br>"
|
||||
+ "<br>\n"
|
||||
+ "<span style=\"font-weight: bold;\">Leader:</span> %players.leader%<br>\n"
|
||||
+ "<span style=\"font-weight: bold;\">Admins:</span> %players.admins.count%<br>\n"
|
||||
+ "<span style=\"font-weight: bold;\">Moderators:</span> %players.moderators.count%<br>\n"
|
||||
+ "<span style=\"font-weight: bold;\">Members:</span> %players.normals.count%<br>\n"
|
||||
+ "<span style=\"font-weight: bold;\">TOTAL:</span> %players.count%<br>\n"
|
||||
+ "</br>\n"
|
||||
+ "<span style=\"font-weight: bold;\">Bank:</span> %money%<br>\n"
|
||||
+ "<br>\n"
|
||||
+ "</div>";
|
||||
|
||||
// Enable the %money% macro. Only do this if you know your economy manager is thread-safe.
|
||||
public static boolean dynmapDescriptionMoney = false;
|
||||
|
||||
// Allow players in faction to see one another on Dynmap (only relevant if Dynmap has 'player-info-protected' enabled)
|
||||
public static boolean dynmapVisibilityByFaction = true;
|
||||
|
||||
// Optional setting to limit which regions to show.
|
||||
// If empty all regions are shown.
|
||||
// Specify Faction either by name or UUID.
|
||||
// To show all regions on a given world, add 'world:<worldname>' to the list.
|
||||
public static Set<String> dynmapVisibleFactions = new HashSet<String>();
|
||||
|
||||
// Optional setting to hide specific Factions.
|
||||
// Specify Faction either by name or UUID.
|
||||
// To hide all regions on a given world, add 'world:<worldname>' to the list.
|
||||
public static Set<String> dynmapHiddenFactions = new HashSet<String>();
|
||||
|
||||
// Region Style
|
||||
public static final transient String DYNMAP_STYLE_LINE_COLOR = "#00FF00";
|
||||
public static final transient double DYNMAP_STYLE_LINE_OPACITY = 0.8D;
|
||||
public static final transient int DYNMAP_STYLE_LINE_WEIGHT = 3;
|
||||
public static final transient String DYNMAP_STYLE_FILL_COLOR = "#00FF00";
|
||||
public static final transient double DYNMAP_STYLE_FILL_OPACITY = 0.35D;
|
||||
public static final transient String DYNMAP_STYLE_HOME_MARKER = "greenflag";
|
||||
public static final transient boolean DYNMAP_STYLE_BOOST = false;
|
||||
|
||||
public static DynmapStyle dynmapDefaultStyle = new DynmapStyle()
|
||||
.setStrokeColor(DYNMAP_STYLE_LINE_COLOR)
|
||||
.setLineOpacity(DYNMAP_STYLE_LINE_OPACITY)
|
||||
.setLineWeight(DYNMAP_STYLE_LINE_WEIGHT)
|
||||
.setFillColor(DYNMAP_STYLE_FILL_COLOR)
|
||||
.setFillOpacity(DYNMAP_STYLE_FILL_OPACITY)
|
||||
.setHomeMarker(DYNMAP_STYLE_HOME_MARKER)
|
||||
.setBoost(DYNMAP_STYLE_BOOST);
|
||||
|
||||
// Optional per Faction style overrides. Any defined replace those in dynmapDefaultStyle.
|
||||
// Specify Faction either by name or UUID.
|
||||
public static Map<String, DynmapStyle> dynmapFactionStyles = ImmutableMap.of(
|
||||
"SafeZone", new DynmapStyle().setStrokeColor("#FF00FF").setFillColor("#FF00FF").setBoost(false),
|
||||
"WarZone", new DynmapStyle().setStrokeColor("#FF0000").setFillColor("#FF0000").setBoost(false)
|
||||
);
|
||||
|
||||
|
||||
//Faction banks, to pay for land claiming and other costs instead of individuals paying for them
|
||||
public static boolean bankEnabled = true;
|
||||
public static boolean bankMembersCanWithdraw = false; //Have to be at least moderator to withdraw or pay money to another faction
|
||||
public static boolean bankFactionPaysCosts = true; //The faction pays for faction command costs, such as sethome
|
||||
public static boolean bankFactionPaysLandCosts = true; //The faction pays for land claiming costs.
|
||||
|
||||
// mainly for other plugins/mods that use a fake player to take actions, which shouldn't be subject to our protections
|
||||
public static Set<String> playersWhoBypassAllProtection = new LinkedHashSet<String>();
|
||||
|
||||
public static Set<String> worldsNoClaiming = new LinkedHashSet<String>();
|
||||
public static Set<String> worldsNoPowerLoss = new LinkedHashSet<String>();
|
||||
public static Set<String> worldsIgnorePvP = new LinkedHashSet<String>();
|
||||
public static Set<String> worldsNoWildernessProtection = new LinkedHashSet<String>();
|
||||
|
||||
// faction-<factionId>
|
||||
public static String vaultPrefix = "faction-%s";
|
||||
public static int defaultMaxVaults = 0;
|
||||
|
||||
public static Backend backEnd = Backend.JSON;
|
||||
|
||||
public static transient int mapHeight = 8;
|
||||
public static transient int mapWidth = 19;
|
||||
public static transient char[] mapKeyChrs = "\\/#$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZ1234567890abcdeghjmnopqrsuvwxyz?".toCharArray();
|
||||
|
||||
static {
|
||||
baseCommandAliases.add("f");
|
||||
|
||||
territoryEnemyDenyCommands.add("home");
|
||||
territoryEnemyDenyCommands.add("sethome");
|
||||
territoryEnemyDenyCommands.add("spawn");
|
||||
territoryEnemyDenyCommands.add("tpahere");
|
||||
territoryEnemyDenyCommands.add("tpaccept");
|
||||
territoryEnemyDenyCommands.add("tpa");
|
||||
|
||||
territoryProtectedMaterials.add(Material.WOODEN_DOOR);
|
||||
territoryProtectedMaterials.add(Material.TRAP_DOOR);
|
||||
territoryProtectedMaterials.add(Material.FENCE_GATE);
|
||||
territoryProtectedMaterials.add(Material.DISPENSER);
|
||||
territoryProtectedMaterials.add(Material.CHEST);
|
||||
territoryProtectedMaterials.add(Material.FURNACE);
|
||||
territoryProtectedMaterials.add(Material.BURNING_FURNACE);
|
||||
territoryProtectedMaterials.add(Material.DIODE_BLOCK_OFF);
|
||||
territoryProtectedMaterials.add(Material.DIODE_BLOCK_ON);
|
||||
territoryProtectedMaterials.add(Material.JUKEBOX);
|
||||
territoryProtectedMaterials.add(Material.BREWING_STAND);
|
||||
territoryProtectedMaterials.add(Material.ENCHANTMENT_TABLE);
|
||||
territoryProtectedMaterials.add(Material.CAULDRON);
|
||||
territoryProtectedMaterials.add(Material.SOIL);
|
||||
territoryProtectedMaterials.add(Material.BEACON);
|
||||
territoryProtectedMaterials.add(Material.ANVIL);
|
||||
territoryProtectedMaterials.add(Material.TRAPPED_CHEST);
|
||||
territoryProtectedMaterials.add(Material.DROPPER);
|
||||
territoryProtectedMaterials.add(Material.HOPPER);
|
||||
|
||||
territoryDenyUseageMaterials.add(Material.FIREBALL);
|
||||
territoryDenyUseageMaterials.add(Material.FLINT_AND_STEEL);
|
||||
territoryDenyUseageMaterials.add(Material.BUCKET);
|
||||
territoryDenyUseageMaterials.add(Material.WATER_BUCKET);
|
||||
territoryDenyUseageMaterials.add(Material.LAVA_BUCKET);
|
||||
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.WOODEN_DOOR);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.TRAP_DOOR);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.FENCE_GATE);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.DISPENSER);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.CHEST);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.FURNACE);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.BURNING_FURNACE);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.DIODE_BLOCK_OFF);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.DIODE_BLOCK_ON);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.JUKEBOX);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.BREWING_STAND);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.ENCHANTMENT_TABLE);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.CAULDRON);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.SOIL);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.BEACON);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.ANVIL);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.TRAPPED_CHEST);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.DROPPER);
|
||||
territoryProtectedMaterialsWhenOffline.add(Material.HOPPER);
|
||||
|
||||
territoryDenyUseageMaterialsWhenOffline.add(Material.FIREBALL);
|
||||
territoryDenyUseageMaterialsWhenOffline.add(Material.FLINT_AND_STEEL);
|
||||
territoryDenyUseageMaterialsWhenOffline.add(Material.BUCKET);
|
||||
territoryDenyUseageMaterialsWhenOffline.add(Material.WATER_BUCKET);
|
||||
territoryDenyUseageMaterialsWhenOffline.add(Material.LAVA_BUCKET);
|
||||
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.BLAZE);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.CAVE_SPIDER);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.CREEPER);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.ENDER_DRAGON);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.ENDERMAN);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.GHAST);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.MAGMA_CUBE);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.PIG_ZOMBIE);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.SILVERFISH);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.SKELETON);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.SPIDER);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.SLIME);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.WITCH);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.WITHER);
|
||||
safeZoneNerfedCreatureTypes.add(EntityType.ZOMBIE);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Persistance
|
||||
// -------------------------------------------- //
|
||||
private static transient Conf i = new Conf();
|
||||
|
||||
public static void load() {
|
||||
P.p.persist.loadOrSaveDefault(i, Conf.class, "conf");
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
P.p.persist.save(i);
|
||||
}
|
||||
|
||||
public enum Backend {
|
||||
JSON,
|
||||
//MYSQL, TODO
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
package com.massivecraft.factions;
|
||||
|
||||
import com.massivecraft.factions.util.MiscUtil;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class FLocation implements Serializable {
|
||||
private static final long serialVersionUID = -8292915234027387983L;
|
||||
private static final boolean worldBorderSupport;
|
||||
private String worldName = "world";
|
||||
private int x = 0;
|
||||
private int z = 0;
|
||||
|
||||
static {
|
||||
boolean worldBorderClassPresent = false;
|
||||
try {
|
||||
Class.forName("org.bukkit.WorldBorder");
|
||||
worldBorderClassPresent = true;
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
|
||||
worldBorderSupport = worldBorderClassPresent;
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// Constructors
|
||||
//----------------------------------------------//
|
||||
|
||||
public FLocation() {
|
||||
|
||||
}
|
||||
|
||||
public FLocation(String worldName, int x, int z) {
|
||||
this.worldName = worldName;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public FLocation(Location location) {
|
||||
this(location.getWorld().getName(), blockToChunk(location.getBlockX()), blockToChunk(location.getBlockZ()));
|
||||
}
|
||||
|
||||
public FLocation(Player player) {
|
||||
this(player.getLocation());
|
||||
}
|
||||
|
||||
public FLocation(FPlayer fplayer) {
|
||||
this(fplayer.getPlayer());
|
||||
}
|
||||
|
||||
public FLocation(Block block) {
|
||||
this(block.getLocation());
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// Getters and Setters
|
||||
//----------------------------------------------//
|
||||
|
||||
public String getWorldName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return Bukkit.getWorld(worldName);
|
||||
}
|
||||
|
||||
public void setWorldName(String worldName) {
|
||||
this.worldName = worldName;
|
||||
}
|
||||
|
||||
public long getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public long getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setZ(int z) {
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public String getCoordString() {
|
||||
return "" + x + "," + z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + this.getWorldName() + "," + this.getCoordString() + "]";
|
||||
}
|
||||
|
||||
public static FLocation fromString(String string) {
|
||||
int index = string.indexOf(",", 0);
|
||||
int start = 1;
|
||||
String worldName = string.substring(start, index);
|
||||
start = index + 1;
|
||||
index = string.indexOf(",", start);
|
||||
int x = Integer.valueOf(string.substring(start, index));
|
||||
int y = Integer.valueOf(string.substring(index + 1, string.length() - 1));
|
||||
return new FLocation(worldName, x, y);
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// Block/Chunk/Region Value Transformation
|
||||
//----------------------------------------------//
|
||||
|
||||
// bit-shifting is used because it's much faster than standard division and multiplication
|
||||
public static int blockToChunk(int blockVal) { // 1 chunk is 16x16 blocks
|
||||
return blockVal >> 4; // ">> 4" == "/ 16"
|
||||
}
|
||||
|
||||
public static int blockToRegion(int blockVal) { // 1 region is 512x512 blocks
|
||||
return blockVal >> 9; // ">> 9" == "/ 512"
|
||||
}
|
||||
|
||||
public static int chunkToRegion(int chunkVal) { // 1 region is 32x32 chunks
|
||||
return chunkVal >> 5; // ">> 5" == "/ 32"
|
||||
}
|
||||
|
||||
public static int chunkToBlock(int chunkVal) {
|
||||
return chunkVal << 4; // "<< 4" == "* 16"
|
||||
}
|
||||
|
||||
public static int regionToBlock(int regionVal) {
|
||||
return regionVal << 9; // "<< 9" == "* 512"
|
||||
}
|
||||
|
||||
public static int regionToChunk(int regionVal) {
|
||||
return regionVal << 5; // "<< 5" == "* 32"
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// Misc Geometry
|
||||
//----------------------------------------------//
|
||||
|
||||
public FLocation getRelative(int dx, int dz) {
|
||||
return new FLocation(this.worldName, this.x + dx, this.z + dz);
|
||||
}
|
||||
|
||||
public double getDistanceTo(FLocation that) {
|
||||
double dx = that.x - this.x;
|
||||
double dz = that.z - this.z;
|
||||
return Math.sqrt(dx * dx + dz * dz);
|
||||
}
|
||||
|
||||
public double getDistanceSquaredTo(FLocation that) {
|
||||
double dx = that.x - this.x;
|
||||
double dz = that.z - this.z;
|
||||
return dx * dx + dz * dz;
|
||||
}
|
||||
|
||||
public boolean isInChunk(Location loc) {
|
||||
if (loc == null) {
|
||||
return false;
|
||||
}
|
||||
Chunk chunk = loc.getChunk();
|
||||
return loc.getWorld().getName().equalsIgnoreCase(getWorldName()) && chunk.getX() == x && chunk.getZ() == z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the chunk represented by this FLocation is outside the world border
|
||||
*
|
||||
* @param buffer the number of chunks from the border that will be treated as "outside"
|
||||
* @return whether this location is outside of the border
|
||||
*/
|
||||
public boolean isOutsideWorldBorder(int buffer) {
|
||||
if (!worldBorderSupport) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WorldBorder border = getWorld().getWorldBorder();
|
||||
Chunk chunk = border.getCenter().getChunk();
|
||||
|
||||
int lim = FLocation.chunkToRegion((int) border.getSize()) - buffer;
|
||||
int diffX = Math.abs(chunk.getX() - x);
|
||||
int diffZ = Math.abs(chunk.getZ() - z);
|
||||
return diffX > lim || diffZ > lim;
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// Some Geometry
|
||||
//----------------------------------------------//
|
||||
public Set<FLocation> getCircle(double radius) {
|
||||
double radiusSquared = radius * radius;
|
||||
|
||||
Set<FLocation> ret = new LinkedHashSet<FLocation>();
|
||||
if (radius <= 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xfrom = (int) Math.floor(this.x - radius);
|
||||
int xto = (int) Math.ceil(this.x + radius);
|
||||
int zfrom = (int) Math.floor(this.z - radius);
|
||||
int zto = (int) Math.ceil(this.z + radius);
|
||||
|
||||
for (int x = xfrom; x <= xto; x++) {
|
||||
for (int z = zfrom; z <= zto; z++) {
|
||||
FLocation potential = new FLocation(this.worldName, x, z);
|
||||
if (this.getDistanceSquaredTo(potential) <= radiusSquared) {
|
||||
ret.add(potential);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static HashSet<FLocation> getArea(FLocation from, FLocation to) {
|
||||
HashSet<FLocation> ret = new HashSet<FLocation>();
|
||||
|
||||
for (long x : MiscUtil.range(from.getX(), to.getX())) {
|
||||
for (long z : MiscUtil.range(from.getZ(), to.getZ())) {
|
||||
ret.add(new FLocation(from.getWorldName(), (int) x, (int) z));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// Comparison
|
||||
//----------------------------------------------//
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// should be fast, with good range and few hash collisions: (x * 512) + z + worldName.hashCode
|
||||
return (this.x << 9) + this.z + (this.worldName != null ? this.worldName.hashCode() : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof FLocation)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FLocation that = (FLocation) obj;
|
||||
return this.x == that.x && this.z == that.z && (this.worldName == null ? that.worldName == null : this.worldName.equals(that.worldName));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
package com.massivecraft.factions;
|
||||
|
||||
import com.massivecraft.factions.iface.EconomyParticipator;
|
||||
import com.massivecraft.factions.iface.RelationParticipator;
|
||||
import com.massivecraft.factions.struct.ChatMode;
|
||||
import com.massivecraft.factions.struct.Relation;
|
||||
import com.massivecraft.factions.struct.Role;
|
||||
import com.massivecraft.factions.util.WarmUpUtil;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Logged in players always have exactly one FPlayer instance. Logged out players may or may not have an FPlayer
|
||||
* instance. They will always have one if they are part of a faction. This is because only players with a faction are
|
||||
* saved to disk (in order to not waste disk space).
|
||||
* <p/>
|
||||
* The FPlayer is linked to a minecraft player using the player name.
|
||||
* <p/>
|
||||
* The same instance is always returned for the same player. This means you can use the == operator. No .equals method
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
public interface FPlayer extends EconomyParticipator {
|
||||
public void login();
|
||||
|
||||
public void logout();
|
||||
|
||||
public Faction getFaction();
|
||||
|
||||
public String getFactionId();
|
||||
|
||||
public boolean hasFaction();
|
||||
|
||||
public void setFaction(Faction faction);
|
||||
|
||||
public boolean willAutoLeave();
|
||||
|
||||
public void setAutoLeave(boolean autoLeave);
|
||||
|
||||
public long getLastFrostwalkerMessage();
|
||||
|
||||
public void setLastFrostwalkerMessage();
|
||||
|
||||
public void setMonitorJoins(boolean monitor);
|
||||
|
||||
public boolean isMonitoringJoins();
|
||||
|
||||
public Role getRole();
|
||||
|
||||
public void setRole(Role role);
|
||||
|
||||
public double getPowerBoost();
|
||||
|
||||
public void setPowerBoost(double powerBoost);
|
||||
|
||||
public Faction getAutoClaimFor();
|
||||
|
||||
public void setAutoClaimFor(Faction faction);
|
||||
|
||||
public boolean isAutoSafeClaimEnabled();
|
||||
|
||||
public void setIsAutoSafeClaimEnabled(boolean enabled);
|
||||
|
||||
public boolean isAutoWarClaimEnabled();
|
||||
|
||||
public void setIsAutoWarClaimEnabled(boolean enabled);
|
||||
|
||||
public boolean isAdminBypassing();
|
||||
|
||||
public boolean isVanished();
|
||||
|
||||
public void setIsAdminBypassing(boolean val);
|
||||
|
||||
public void setChatMode(ChatMode chatMode);
|
||||
|
||||
public ChatMode getChatMode();
|
||||
|
||||
public void setIgnoreAllianceChat(boolean ignore);
|
||||
|
||||
public boolean isIgnoreAllianceChat();
|
||||
|
||||
public void setSpyingChat(boolean chatSpying);
|
||||
|
||||
public boolean isSpyingChat();
|
||||
|
||||
public boolean showScoreboard();
|
||||
|
||||
public void setShowScoreboard(boolean show);
|
||||
|
||||
// FIELD: account
|
||||
public String getAccountId();
|
||||
|
||||
public void resetFactionData(boolean doSpoutUpdate);
|
||||
|
||||
public void resetFactionData();
|
||||
|
||||
public long getLastLoginTime();
|
||||
|
||||
public void setLastLoginTime(long lastLoginTime);
|
||||
|
||||
public boolean isMapAutoUpdating();
|
||||
|
||||
public void setMapAutoUpdating(boolean mapAutoUpdating);
|
||||
|
||||
public boolean hasLoginPvpDisabled();
|
||||
|
||||
public FLocation getLastStoodAt();
|
||||
|
||||
public void setLastStoodAt(FLocation flocation);
|
||||
|
||||
public String getTitle();
|
||||
|
||||
public void setTitle(String title);
|
||||
|
||||
public String getName();
|
||||
|
||||
public String getTag();
|
||||
|
||||
// Base concatenations:
|
||||
|
||||
public String getNameAndSomething(String something);
|
||||
|
||||
public String getNameAndTitle();
|
||||
|
||||
public String getNameAndTag();
|
||||
|
||||
// Colored concatenations:
|
||||
// These are used in information messages
|
||||
|
||||
public String getNameAndTitle(Faction faction);
|
||||
|
||||
public String getNameAndTitle(FPlayer fplayer);
|
||||
|
||||
// Chat CoreTag:
|
||||
// These are injected into the format of global chat messages.
|
||||
|
||||
public String getChatTag();
|
||||
|
||||
// Colored Chat CoreTag
|
||||
public String getChatTag(Faction faction);
|
||||
|
||||
public String getChatTag(FPlayer fplayer);
|
||||
|
||||
public int getKills();
|
||||
|
||||
public int getDeaths();
|
||||
|
||||
|
||||
// -------------------------------
|
||||
// Relation and relation colors
|
||||
// -------------------------------
|
||||
|
||||
@Override
|
||||
public String describeTo(RelationParticipator that, boolean ucfirst);
|
||||
|
||||
@Override
|
||||
public String describeTo(RelationParticipator that);
|
||||
|
||||
@Override
|
||||
public Relation getRelationTo(RelationParticipator rp);
|
||||
|
||||
@Override
|
||||
public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful);
|
||||
|
||||
public Relation getRelationToLocation();
|
||||
|
||||
@Override
|
||||
public ChatColor getColorTo(RelationParticipator rp);
|
||||
|
||||
//----------------------------------------------//
|
||||
// Health
|
||||
//----------------------------------------------//
|
||||
public void heal(int amnt);
|
||||
|
||||
|
||||
//----------------------------------------------//
|
||||
// Power
|
||||
//----------------------------------------------//
|
||||
public double getPower();
|
||||
|
||||
public void alterPower(double delta);
|
||||
|
||||
public double getPowerMax();
|
||||
|
||||
public double getPowerMin();
|
||||
|
||||
public int getPowerRounded();
|
||||
|
||||
public int getPowerMaxRounded();
|
||||
|
||||
public int getPowerMinRounded();
|
||||
|
||||
public void updatePower();
|
||||
|
||||
public void losePowerFromBeingOffline();
|
||||
|
||||
public void onDeath();
|
||||
|
||||
//----------------------------------------------//
|
||||
// Territory
|
||||
//----------------------------------------------//
|
||||
public boolean isInOwnTerritory();
|
||||
|
||||
public boolean isInOthersTerritory();
|
||||
|
||||
public boolean isInAllyTerritory();
|
||||
|
||||
public boolean isInNeutralTerritory();
|
||||
|
||||
public boolean isInEnemyTerritory();
|
||||
|
||||
public void sendFactionHereMessage(Faction from);
|
||||
|
||||
// -------------------------------
|
||||
// Actions
|
||||
// -------------------------------
|
||||
|
||||
public void leave(boolean makePay);
|
||||
|
||||
public boolean canClaimForFaction(Faction forFaction);
|
||||
|
||||
public boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure);
|
||||
|
||||
public boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure);
|
||||
|
||||
public void msg(String str, Object... args);
|
||||
|
||||
public String getId();
|
||||
|
||||
public Player getPlayer();
|
||||
|
||||
public boolean isOnline();
|
||||
|
||||
public void sendMessage(String message);
|
||||
|
||||
public void sendMessage(List<String> messages);
|
||||
|
||||
public boolean isOnlineAndVisibleTo(Player me);
|
||||
|
||||
public void remove();
|
||||
|
||||
public boolean isOffline();
|
||||
|
||||
public void setId(String id);
|
||||
|
||||
// -------------------------------
|
||||
// Warmups
|
||||
// -------------------------------
|
||||
|
||||
public boolean isWarmingUp();
|
||||
|
||||
public WarmUpUtil.Warmup getWarmupType();
|
||||
|
||||
public void addWarmup(WarmUpUtil.Warmup warmup, int taskId);
|
||||
|
||||
public void stopWarmup();
|
||||
|
||||
public void clearWarmup();
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.massivecraft.factions;
|
||||
|
||||
import com.massivecraft.factions.zcore.persist.json.JSONFPlayers;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class FPlayers {
|
||||
protected static FPlayers instance = getFPlayersImpl();
|
||||
|
||||
public abstract void clean();
|
||||
|
||||
public static FPlayers getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static FPlayers getFPlayersImpl() {
|
||||
switch (Conf.backEnd) {
|
||||
case JSON:
|
||||
return new JSONFPlayers();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract Collection<FPlayer> getOnlinePlayers();
|
||||
|
||||
public abstract FPlayer getByPlayer(Player player);
|
||||
|
||||
public abstract Collection<FPlayer> getAllFPlayers();
|
||||
|
||||
public abstract void forceSave();
|
||||
|
||||
public abstract void forceSave(boolean sync);
|
||||
|
||||
public abstract FPlayer getByOfflinePlayer(OfflinePlayer player);
|
||||
|
||||
public abstract FPlayer getById(String string);
|
||||
|
||||
public abstract void load();
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
package com.massivecraft.factions;
|
||||
|
||||
import com.massivecraft.factions.eco.EcoResult;
|
||||
import com.massivecraft.factions.iface.EconomyParticipator;
|
||||
import com.massivecraft.factions.iface.RelationParticipator;
|
||||
import com.massivecraft.factions.struct.Relation;
|
||||
import com.massivecraft.factions.struct.Role;
|
||||
import com.massivecraft.factions.util.LazyLocation;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public interface Faction extends EconomyParticipator {
|
||||
public HashMap<String, List<String>> getAnnouncements();
|
||||
|
||||
public ConcurrentHashMap<String, LazyLocation> getWarps();
|
||||
|
||||
public LazyLocation getWarp(String name);
|
||||
|
||||
public void setWarp(String name, LazyLocation loc);
|
||||
|
||||
public boolean isWarp(String name);
|
||||
|
||||
public boolean removeWarp(String name);
|
||||
|
||||
public void clearWarps();
|
||||
|
||||
public int getMaxVaults();
|
||||
|
||||
public void setMaxVaults(int value);
|
||||
|
||||
public void addAnnouncement(FPlayer fPlayer, String msg);
|
||||
|
||||
public void sendUnreadAnnouncements(FPlayer fPlayer);
|
||||
|
||||
public void removeAnnouncements(FPlayer fPlayer);
|
||||
|
||||
public Set<String> getInvites();
|
||||
|
||||
public String getId();
|
||||
|
||||
public void invite(FPlayer fplayer);
|
||||
|
||||
public void deinvite(FPlayer fplayer);
|
||||
|
||||
public boolean isInvited(FPlayer fplayer);
|
||||
|
||||
public boolean getOpen();
|
||||
|
||||
public void setOpen(boolean isOpen);
|
||||
|
||||
public boolean isPeaceful();
|
||||
|
||||
public void setPeaceful(boolean isPeaceful);
|
||||
|
||||
public void setPeacefulExplosionsEnabled(boolean val);
|
||||
|
||||
public boolean getPeacefulExplosionsEnabled();
|
||||
|
||||
public boolean noExplosionsInTerritory();
|
||||
|
||||
public boolean isPermanent();
|
||||
|
||||
public void setPermanent(boolean isPermanent);
|
||||
|
||||
public String getTag();
|
||||
|
||||
public String getTag(String prefix);
|
||||
|
||||
public String getTag(Faction otherFaction);
|
||||
|
||||
public String getTag(FPlayer otherFplayer);
|
||||
|
||||
public void setTag(String str);
|
||||
|
||||
public String getComparisonTag();
|
||||
|
||||
public String getDescription();
|
||||
|
||||
public void setDescription(String value);
|
||||
|
||||
public void setHome(Location home);
|
||||
|
||||
public boolean hasHome();
|
||||
|
||||
public Location getHome();
|
||||
|
||||
public long getFoundedDate();
|
||||
|
||||
public void setFoundedDate(long newDate);
|
||||
|
||||
public void confirmValidHome();
|
||||
|
||||
public String getAccountId();
|
||||
|
||||
public Integer getPermanentPower();
|
||||
|
||||
public void setPermanentPower(Integer permanentPower);
|
||||
|
||||
public boolean hasPermanentPower();
|
||||
|
||||
public double getPowerBoost();
|
||||
|
||||
public void setPowerBoost(double powerBoost);
|
||||
|
||||
public boolean noPvPInTerritory();
|
||||
|
||||
public boolean noMonstersInTerritory();
|
||||
|
||||
public boolean isNormal();
|
||||
|
||||
@Deprecated
|
||||
public boolean isNone();
|
||||
|
||||
public boolean isWilderness();
|
||||
|
||||
public boolean isSafeZone();
|
||||
|
||||
public boolean isWarZone();
|
||||
|
||||
public boolean isPlayerFreeType();
|
||||
|
||||
public boolean isPowerFrozen();
|
||||
|
||||
public void setLastDeath(long time);
|
||||
|
||||
public int getKills();
|
||||
|
||||
public int getDeaths();
|
||||
|
||||
// -------------------------------
|
||||
// Relation and relation colors
|
||||
// -------------------------------
|
||||
|
||||
@Override
|
||||
public String describeTo(RelationParticipator that, boolean ucfirst);
|
||||
|
||||
@Override
|
||||
public String describeTo(RelationParticipator that);
|
||||
|
||||
@Override
|
||||
public Relation getRelationTo(RelationParticipator rp);
|
||||
|
||||
@Override
|
||||
public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful);
|
||||
|
||||
@Override
|
||||
public ChatColor getColorTo(RelationParticipator rp);
|
||||
|
||||
public Relation getRelationWish(Faction otherFaction);
|
||||
|
||||
public void setRelationWish(Faction otherFaction, Relation relation);
|
||||
|
||||
public int getRelationCount(Relation relation);
|
||||
|
||||
// ----------------------------------------------//
|
||||
// Power
|
||||
// ----------------------------------------------//
|
||||
public double getPower();
|
||||
|
||||
public double getPowerMax();
|
||||
|
||||
public int getPowerRounded();
|
||||
|
||||
public int getPowerMaxRounded();
|
||||
|
||||
public int getLandRounded();
|
||||
|
||||
public int getLandRoundedInWorld(String worldName);
|
||||
|
||||
public boolean hasLandInflation();
|
||||
|
||||
// -------------------------------
|
||||
// FPlayers
|
||||
// -------------------------------
|
||||
|
||||
// maintain the reference list of FPlayers in this faction
|
||||
public void refreshFPlayers();
|
||||
|
||||
public boolean addFPlayer(FPlayer fplayer);
|
||||
|
||||
public boolean removeFPlayer(FPlayer fplayer);
|
||||
|
||||
public int getSize();
|
||||
|
||||
public Set<FPlayer> getFPlayers();
|
||||
|
||||
public Set<FPlayer> getFPlayersWhereOnline(boolean online);
|
||||
|
||||
public FPlayer getFPlayerAdmin();
|
||||
|
||||
public ArrayList<FPlayer> getFPlayersWhereRole(Role role);
|
||||
|
||||
public ArrayList<Player> getOnlinePlayers();
|
||||
|
||||
// slightly faster check than getOnlinePlayers() if you just want to see if
|
||||
// there are any players online
|
||||
public boolean hasPlayersOnline();
|
||||
|
||||
public void memberLoggedOff();
|
||||
|
||||
// used when current leader is about to be removed from the faction;
|
||||
// promotes new leader, or disbands faction if no other members left
|
||||
public void promoteNewLeader();
|
||||
|
||||
// ----------------------------------------------//
|
||||
// Messages
|
||||
// ----------------------------------------------//
|
||||
public void msg(String message, Object... args);
|
||||
|
||||
public void sendMessage(String message);
|
||||
|
||||
public void sendMessage(List<String> messages);
|
||||
|
||||
// ----------------------------------------------//
|
||||
// Ownership of specific claims
|
||||
// ----------------------------------------------//
|
||||
|
||||
public Map<FLocation, Set<String>> getClaimOwnership();
|
||||
|
||||
public void clearAllClaimOwnership();
|
||||
|
||||
public void clearClaimOwnership(FLocation loc);
|
||||
|
||||
public void clearClaimOwnership(FPlayer player);
|
||||
|
||||
public int getCountOfClaimsWithOwners();
|
||||
|
||||
public boolean doesLocationHaveOwnersSet(FLocation loc);
|
||||
|
||||
public boolean isPlayerInOwnerList(FPlayer player, FLocation loc);
|
||||
|
||||
public void setPlayerAsOwner(FPlayer player, FLocation loc);
|
||||
|
||||
public void removePlayerAsOwner(FPlayer player, FLocation loc);
|
||||
|
||||
public Set<String> getOwnerList(FLocation loc);
|
||||
|
||||
public String getOwnerListString(FLocation loc);
|
||||
|
||||
public boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc);
|
||||
|
||||
// ----------------------------------------------//
|
||||
// Persistance and entity management
|
||||
// ----------------------------------------------//
|
||||
public void remove();
|
||||
|
||||
public Set<FLocation> getAllClaims();
|
||||
|
||||
public void setId(String id);
|
||||
|
||||
// ----------------------------------------------//
|
||||
// Economy Faction stash
|
||||
// ----------------------------------------------//
|
||||
public double getStash();
|
||||
|
||||
public EcoResult addToStash(double amount);
|
||||
|
||||
public EcoResult takeFromStash(double amount);
|
||||
|
||||
public void setStash(double amount);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.massivecraft.factions;
|
||||
|
||||
import com.massivecraft.factions.zcore.persist.json.JSONFactions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class Factions {
|
||||
protected static Factions instance = getFactionsImpl();
|
||||
|
||||
public abstract Faction getFactionById(String id);
|
||||
|
||||
public abstract Faction getByTag(String str);
|
||||
|
||||
public abstract Faction getBestTagMatch(String start);
|
||||
|
||||
public abstract boolean isTagTaken(String str);
|
||||
|
||||
public abstract boolean isValidFactionId(String id);
|
||||
|
||||
public abstract Faction createFaction();
|
||||
|
||||
public abstract void removeFaction(String id);
|
||||
|
||||
public abstract Set<String> getFactionTags();
|
||||
|
||||
public abstract ArrayList<Faction> getAllFactions();
|
||||
|
||||
@Deprecated
|
||||
public abstract Faction getNone();
|
||||
|
||||
public abstract Faction getWilderness();
|
||||
|
||||
public abstract Faction getSafeZone();
|
||||
|
||||
public abstract Faction getWarZone();
|
||||
|
||||
public abstract void forceSave();
|
||||
|
||||
public abstract void forceSave(boolean sync);
|
||||
|
||||
public static Factions getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static Factions getFactionsImpl() {
|
||||
switch (Conf.backEnd) {
|
||||
case JSON:
|
||||
return new JSONFactions();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void load();
|
||||
}
|
|
@ -0,0 +1,334 @@
|
|||
package com.massivecraft.factions;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.massivecraft.factions.cmd.CmdAutoHelp;
|
||||
import com.massivecraft.factions.cmd.FCmdRoot;
|
||||
import com.massivecraft.factions.integration.Econ;
|
||||
import com.massivecraft.factions.integration.Essentials;
|
||||
import com.massivecraft.factions.integration.Worldguard;
|
||||
import com.massivecraft.factions.integration.dynmap.EngineDynmap;
|
||||
import com.massivecraft.factions.listeners.*;
|
||||
import com.massivecraft.factions.struct.ChatMode;
|
||||
import com.massivecraft.factions.util.*;
|
||||
import com.massivecraft.factions.zcore.MPlugin;
|
||||
import com.massivecraft.factions.zcore.util.TextUtil;
|
||||
import net.grandtheftmc.core.menus.MenuManager;
|
||||
import net.milkbowl.vault.permission.Permission;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
public class P extends MPlugin {
|
||||
|
||||
// Our single plugin instance.
|
||||
// Single 4 life.
|
||||
public static P p;
|
||||
public static Permission perms = null;
|
||||
|
||||
// Persistence related
|
||||
private boolean locked = false;
|
||||
|
||||
public boolean getLocked() {
|
||||
return this.locked;
|
||||
}
|
||||
|
||||
public void setLocked(boolean val) {
|
||||
this.locked = val;
|
||||
this.setAutoSave(val);
|
||||
}
|
||||
|
||||
private Integer AutoLeaveTask = null;
|
||||
|
||||
// Commands
|
||||
public FCmdRoot cmdBase;
|
||||
public CmdAutoHelp cmdAutoHelp;
|
||||
|
||||
private boolean hookedPlayervaults;
|
||||
|
||||
public P() {
|
||||
p = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
if (!preEnable()) {
|
||||
return;
|
||||
}
|
||||
this.loadSuccessful = false;
|
||||
saveDefaultConfig();
|
||||
|
||||
// Load Conf from disk
|
||||
Conf.load();
|
||||
Essentials.setup();
|
||||
FPlayers.getInstance().load();
|
||||
Factions.getInstance().load();
|
||||
for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) {
|
||||
Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId());
|
||||
if (faction == null) {
|
||||
log("Invalid cartel id on " + fPlayer.getName() + ":" + fPlayer.getFactionId());
|
||||
fPlayer.resetFactionData(false);
|
||||
continue;
|
||||
}
|
||||
faction.addFPlayer(fPlayer);
|
||||
}
|
||||
Board.getInstance().load();
|
||||
Board.getInstance().clean();
|
||||
|
||||
// Add Base Commands
|
||||
this.cmdBase = new FCmdRoot();
|
||||
this.cmdAutoHelp = new CmdAutoHelp();
|
||||
this.getBaseCommands().add(cmdBase);
|
||||
|
||||
Econ.setup();
|
||||
setupPermissions();
|
||||
|
||||
if (Conf.worldGuardChecking || Conf.worldGuardBuildPriority) {
|
||||
Worldguard.init(this);
|
||||
}
|
||||
|
||||
EngineDynmap.getInstance().init();
|
||||
|
||||
// start up task which runs the autoLeaveAfterDaysOfInactivity routine
|
||||
startAutoLeaveTask(false);
|
||||
|
||||
// Register Event Handlers
|
||||
getServer().getPluginManager().registerEvents(new FactionsPlayerListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new FactionsChatListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new FactionsEntityListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new FactionsExploitListener(), this);
|
||||
getServer().getPluginManager().registerEvents(new FactionsBlockListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new MenuListener(), this);
|
||||
|
||||
// since some other plugins execute commands directly through this command interface, provide it
|
||||
this.getCommand(this.refCommand).setExecutor(this);
|
||||
|
||||
MenuManager.addMenu("carteltop", 54, "&cTop Cartels");
|
||||
|
||||
postEnable();
|
||||
this.loadSuccessful = true;
|
||||
}
|
||||
|
||||
private boolean setupPermissions() {
|
||||
try {
|
||||
RegisteredServiceProvider<Permission> rsp = getServer().getServicesManager().getRegistration(Permission.class);
|
||||
if (rsp != null) {
|
||||
perms = rsp.getProvider();
|
||||
}
|
||||
} catch (NoClassDefFoundError ex) {
|
||||
return false;
|
||||
}
|
||||
return perms != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GsonBuilder getGsonBuilder() {
|
||||
Type mapFLocToStringSetType = new TypeToken<Map<FLocation, Set<String>>>() {
|
||||
}.getType();
|
||||
|
||||
return new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE).registerTypeAdapter(LazyLocation.class, new MyLocationTypeAdapter()).registerTypeAdapter(mapFLocToStringSetType, new MapFLocToStringSetTypeAdapter()).registerTypeAdapterFactory(EnumTypeAdapter.ENUM_FACTORY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// only save data if plugin actually completely loaded successfully
|
||||
if (this.loadSuccessful) {
|
||||
Conf.save();
|
||||
}
|
||||
if (AutoLeaveTask != null) {
|
||||
this.getServer().getScheduler().cancelTask(AutoLeaveTask);
|
||||
AutoLeaveTask = null;
|
||||
}
|
||||
|
||||
super.onDisable();
|
||||
}
|
||||
|
||||
public void startAutoLeaveTask(boolean restartIfRunning) {
|
||||
if (AutoLeaveTask != null) {
|
||||
if (!restartIfRunning) {
|
||||
return;
|
||||
}
|
||||
this.getServer().getScheduler().cancelTask(AutoLeaveTask);
|
||||
}
|
||||
|
||||
if (Conf.autoLeaveRoutineRunsEveryXMinutes > 0.0) {
|
||||
long ticks = (long) (20 * 60 * Conf.autoLeaveRoutineRunsEveryXMinutes);
|
||||
AutoLeaveTask = getServer().getScheduler().scheduleSyncRepeatingTask(this, new AutoLeaveTask(), ticks, ticks);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAutoSave() {
|
||||
//Board.getInstance().forceSave(); Not sure why this was there as it's called after the board is already saved.
|
||||
Conf.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean logPlayerCommands() {
|
||||
return Conf.logPlayerCommands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly) {
|
||||
return sender instanceof Player && FactionsPlayerListener.preventCommand(commandString, (Player) sender) || super.handleCommand(sender, commandString, testOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] split) {
|
||||
if (split.length == 0) {
|
||||
return handleCommand(sender, "/c help", false);
|
||||
}
|
||||
|
||||
// otherwise, needs to be handled; presumably another plugin directly ran the command
|
||||
String cmd = Conf.baseCommandAliases.isEmpty() ? "/c" : "/" + Conf.baseCommandAliases.get(0);
|
||||
return handleCommand(sender, cmd + " " + TextUtil.implode(Arrays.asList(split), " "), false);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------- //
|
||||
// Functions for other plugins to hook into
|
||||
// -------------------------------------------- //
|
||||
|
||||
// This value will be updated whenever new hooks are added
|
||||
public int hookSupportVersion() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
// If another plugin is handling insertion of chat tags, this should be used to notify Factions
|
||||
public void handleFactionTagExternally(boolean notByFactions) {
|
||||
Conf.chatTagHandledByAnotherPlugin = notByFactions;
|
||||
}
|
||||
|
||||
// Simply put, should this chat event be left for Factions to handle? For now, that means players with Faction Chat
|
||||
// enabled or use of the Factions f command without a slash; combination of isPlayerFactionChatting() and isFactionsCommand()
|
||||
|
||||
public boolean shouldLetFactionsHandleThisChat(AsyncPlayerChatEvent event) {
|
||||
return event != null && (isPlayerFactionChatting(event.getPlayer()) || isFactionsCommand(event.getMessage()));
|
||||
}
|
||||
|
||||
// Does player have Faction Chat enabled? If so, chat plugins should preferably not do channels,
|
||||
// local chat, or anything else which targets individual recipients, so Faction Chat can be done
|
||||
public boolean isPlayerFactionChatting(Player player) {
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
FPlayer me = FPlayers.getInstance().getByPlayer(player);
|
||||
|
||||
return me != null && me.getChatMode().isAtLeast(ChatMode.ALLIANCE);
|
||||
}
|
||||
|
||||
// Is this chat message actually a Factions command, and thus should be left alone by other plugins?
|
||||
|
||||
// TODO: GET THIS BACK AND WORKING
|
||||
|
||||
public boolean isFactionsCommand(String check) {
|
||||
return !(check == null || check.isEmpty()) && this.handleCommand(null, check, true);
|
||||
}
|
||||
|
||||
// Get a player's faction tag (faction name), mainly for usage by chat plugins for local/channel chat
|
||||
public String getPlayerFactionTag(Player player) {
|
||||
return getPlayerFactionTagRelation(player, null);
|
||||
}
|
||||
|
||||
// Same as above, but with relation (enemy/neutral/ally) coloring potentially added to the tag
|
||||
public String getPlayerFactionTagRelation(Player speaker, Player listener) {
|
||||
String tag = "~";
|
||||
|
||||
if (speaker == null) {
|
||||
return tag;
|
||||
}
|
||||
|
||||
FPlayer me = FPlayers.getInstance().getByPlayer(speaker);
|
||||
if (me == null) {
|
||||
return tag;
|
||||
}
|
||||
|
||||
// if listener isn't set, or config option is disabled, give back uncolored tag
|
||||
if (listener == null || !Conf.chatTagRelationColored) {
|
||||
tag = me.getChatTag().trim();
|
||||
} else {
|
||||
FPlayer you = FPlayers.getInstance().getByPlayer(listener);
|
||||
if (you == null) {
|
||||
tag = me.getChatTag().trim();
|
||||
} else // everything checks out, give the colored tag
|
||||
{
|
||||
tag = me.getChatTag(you).trim();
|
||||
}
|
||||
}
|
||||
if (tag.isEmpty()) {
|
||||
tag = "~";
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
// Get a player's title within their faction, mainly for usage by chat plugins for local/channel chat
|
||||
public String getPlayerTitle(Player player) {
|
||||
if (player == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
FPlayer me = FPlayers.getInstance().getByPlayer(player);
|
||||
if (me == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return me.getTitle().trim();
|
||||
}
|
||||
|
||||
// Get a list of all faction tags (names)
|
||||
public Set<String> getFactionTags() {
|
||||
return Factions.getInstance().getFactionTags();
|
||||
}
|
||||
|
||||
// Get a list of all players in the specified faction
|
||||
public Set<String> getPlayersInFaction(String factionTag) {
|
||||
Set<String> players = new HashSet<String>();
|
||||
Faction faction = Factions.getInstance().getByTag(factionTag);
|
||||
if (faction != null) {
|
||||
for (FPlayer fplayer : faction.getFPlayers()) {
|
||||
players.add(fplayer.getName());
|
||||
}
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
// Get a list of all online players in the specified faction
|
||||
public Set<String> getOnlinePlayersInFaction(String factionTag) {
|
||||
Set<String> players = new HashSet<String>();
|
||||
Faction faction = Factions.getInstance().getByTag(factionTag);
|
||||
if (faction != null) {
|
||||
for (FPlayer fplayer : faction.getFPlayersWhereOnline(true)) {
|
||||
players.add(fplayer.getName());
|
||||
}
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
public String getPrimaryGroup(OfflinePlayer player) {
|
||||
return perms == null || !perms.hasGroupSupport() ? " " : perms.getPrimaryGroup(Bukkit.getWorlds().get(0).toString(), player);
|
||||
}
|
||||
|
||||
public void debug(Level level, String s) {
|
||||
if (getConfig().getBoolean("debug", false)) {
|
||||
getLogger().log(level, s);
|
||||
}
|
||||
}
|
||||
|
||||
public void debug(String s) {
|
||||
debug(Level.INFO, s);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.Faction;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
public class CmdAHome extends FCommand {
|
||||
|
||||
public CmdAHome() {
|
||||
super();
|
||||
this.aliases.add("ahome");
|
||||
|
||||
this.requiredArgs.add("player name");
|
||||
|
||||
this.permission = Permission.AHOME.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = false;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
FPlayer target = argAsBestFPlayerMatch(0);
|
||||
if (target == null) {
|
||||
msg(TL.GENERIC_NOPLAYERMATCH, argAsString(0));
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.isOnline()) {
|
||||
Faction faction = target.getFaction();
|
||||
if (faction.hasHome()) {
|
||||
target.getPlayer().teleport(faction.getHome(), PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
msg(TL.COMMAND_AHOME_SUCCESS, target.getName());
|
||||
target.msg(TL.COMMAND_AHOME_TARGET);
|
||||
} else {
|
||||
msg(TL.COMMAND_AHOME_NOHOME, target.getName());
|
||||
}
|
||||
} else {
|
||||
msg(TL.COMMAND_AHOME_OFFLINE, target.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_AHOME_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.FPlayers;
|
||||
import com.massivecraft.factions.Faction;
|
||||
import com.massivecraft.factions.event.FPlayerJoinEvent;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.struct.Role;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class CmdAdmin extends FCommand {
|
||||
|
||||
public CmdAdmin() {
|
||||
super();
|
||||
this.aliases.add("boss");
|
||||
this.aliases.add("setboss");
|
||||
this.aliases.add("admin");
|
||||
this.aliases.add("setadmin");
|
||||
this.aliases.add("leader");
|
||||
this.aliases.add("setleader");
|
||||
|
||||
this.requiredArgs.add("player name");
|
||||
//this.optionalArgs.put("", "");
|
||||
|
||||
this.permission = Permission.ADMIN.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = false;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
FPlayer fyou = this.argAsBestFPlayerMatch(0);
|
||||
if (fyou == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean permAny = Permission.ADMIN_ANY.has(sender, false);
|
||||
Faction targetFaction = fyou.getFaction();
|
||||
|
||||
if (targetFaction != myFaction && !permAny) {
|
||||
msg(TL.COMMAND_ADMIN_NOTMEMBER, fyou.describeTo(fme, true));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fme != null && fme.getRole() != Role.ADMIN && !permAny) {
|
||||
msg(TL.COMMAND_ADMIN_NOTADMIN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fyou == fme && !permAny) {
|
||||
msg(TL.COMMAND_ADMIN_TARGETSELF);
|
||||
return;
|
||||
}
|
||||
|
||||
// only perform a FPlayerJoinEvent when newLeader isn't actually in the faction
|
||||
if (fyou.getFaction() != targetFaction) {
|
||||
FPlayerJoinEvent event = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), targetFaction, FPlayerJoinEvent.PlayerJoinReason.LEADER);
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FPlayer admin = targetFaction.getFPlayerAdmin();
|
||||
|
||||
// if target player is currently admin, demote and replace him
|
||||
if (fyou == admin) {
|
||||
targetFaction.promoteNewLeader();
|
||||
msg(TL.COMMAND_ADMIN_DEMOTES, fyou.describeTo(fme, true));
|
||||
fyou.msg(TL.COMMAND_ADMIN_DEMOTED, senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fyou, true));
|
||||
return;
|
||||
}
|
||||
|
||||
// promote target player, and demote existing admin if one exists
|
||||
if (admin != null) {
|
||||
admin.setRole(Role.MODERATOR);
|
||||
}
|
||||
fyou.setRole(Role.ADMIN);
|
||||
msg(TL.COMMAND_ADMIN_PROMOTES, fyou.describeTo(fme, true));
|
||||
|
||||
// Inform all players
|
||||
for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) {
|
||||
fplayer.msg(TL.COMMAND_ADMIN_PROMOTED, senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer, true), fyou.describeTo(fplayer), targetFaction.describeTo(fplayer));
|
||||
}
|
||||
}
|
||||
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_ADMIN_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CmdAnnounce extends FCommand {
|
||||
|
||||
public CmdAnnounce() {
|
||||
super();
|
||||
this.aliases.add("ann");
|
||||
this.aliases.add("announce");
|
||||
|
||||
this.requiredArgs.add("message");
|
||||
this.errorOnToManyArgs = false;
|
||||
|
||||
this.permission = Permission.ANNOUNCE.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = true;
|
||||
senderMustBeModerator = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
String prefix = ChatColor.GREEN + myFaction.getTag() + ChatColor.YELLOW + " [" + ChatColor.GRAY + me.getName() + ChatColor.YELLOW + "] " + ChatColor.RESET;
|
||||
String message = StringUtils.join(args, " ");
|
||||
|
||||
for (Player player : myFaction.getOnlinePlayers()) {
|
||||
player.sendMessage(prefix + message);
|
||||
}
|
||||
|
||||
// Add for offline players.
|
||||
for (FPlayer fp : myFaction.getFPlayersWhereOnline(false)) {
|
||||
myFaction.addAnnouncement(fp, prefix + message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_ANNOUNCE_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Faction;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.struct.Role;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdAutoClaim extends FCommand {
|
||||
|
||||
public CmdAutoClaim() {
|
||||
super();
|
||||
this.aliases.add("autoclaim");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("cartel", "your");
|
||||
|
||||
this.permission = Permission.AUTOCLAIM.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
Faction forFaction = this.argAsFaction(0, myFaction);
|
||||
if (forFaction == null || forFaction == fme.getAutoClaimFor()) {
|
||||
fme.setAutoClaimFor(null);
|
||||
msg(TL.COMMAND_AUTOCLAIM_DISABLED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fme.canClaimForFaction(forFaction)) {
|
||||
if (myFaction == forFaction) {
|
||||
msg(TL.COMMAND_AUTOCLAIM_REQUIREDRANK, Role.MODERATOR.getTranslation());
|
||||
} else {
|
||||
msg(TL.COMMAND_AUTOCLAIM_OTHERFACTION, forFaction.describeTo(fme));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fme.setAutoClaimFor(forFaction);
|
||||
|
||||
msg(TL.COMMAND_AUTOCLAIM_ENABLED, forFaction.describeTo(fme));
|
||||
fme.attemptClaim(forFaction, me.getLocation(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_AUTOCLAIM_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.P;
|
||||
import com.massivecraft.factions.zcore.CommandVisibility;
|
||||
import com.massivecraft.factions.zcore.MCommand;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CmdAutoHelp extends MCommand<P> {
|
||||
|
||||
public CmdAutoHelp() {
|
||||
super(P.p);
|
||||
this.aliases.add("?");
|
||||
this.aliases.add("h");
|
||||
this.aliases.add("help");
|
||||
|
||||
this.setHelpShort("");
|
||||
|
||||
this.optionalArgs.put("page", "1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
if (this.commandChain.size() == 0) {
|
||||
return;
|
||||
}
|
||||
MCommand<?> pcmd = this.commandChain.get(this.commandChain.size() - 1);
|
||||
|
||||
ArrayList<String> lines = new ArrayList<String>();
|
||||
|
||||
lines.addAll(pcmd.helpLong);
|
||||
|
||||
for (MCommand<?> scmd : pcmd.subCommands) {
|
||||
if (scmd.visibility == CommandVisibility.VISIBLE || (scmd.visibility == CommandVisibility.SECRET && scmd.validSenderPermissions(sender, false))) {
|
||||
lines.add(scmd.getUseageTemplate(this.commandChain, true));
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage(p.txt.getPage(lines, this.argAsInt(0, 1), TL.COMMAND_AUTOHELP_HELPFOR.toString() + pcmd.aliases.get(0) + "\""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_HELP_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdBoom extends FCommand {
|
||||
|
||||
public CmdBoom() {
|
||||
super();
|
||||
this.aliases.add("noboom");
|
||||
this.aliases.add("explosions");
|
||||
this.aliases.add("toggleexplosions");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("on/off", "flip");
|
||||
|
||||
this.permission = Permission.NO_BOOM.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = true;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
if (!myFaction.isPeaceful()) {
|
||||
fme.msg(TL.COMMAND_BOOM_PEACEFULONLY);
|
||||
return;
|
||||
}
|
||||
|
||||
// if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay
|
||||
if (!payForCommand(Conf.econCostNoBoom, TL.COMMAND_BOOM_TOTOGGLE, TL.COMMAND_BOOM_FORTOGGLE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
myFaction.setPeacefulExplosionsEnabled(this.argAsBool(0, !myFaction.getPeacefulExplosionsEnabled()));
|
||||
|
||||
String enabled = myFaction.noExplosionsInTerritory() ? TL.GENERIC_DISABLED.toString() : TL.GENERIC_ENABLED.toString();
|
||||
|
||||
// Inform
|
||||
myFaction.msg(TL.COMMAND_BOOM_ENABLED, fme.describeTo(myFaction), enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_BOOM_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.P;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdBypass extends FCommand {
|
||||
|
||||
public CmdBypass() {
|
||||
super();
|
||||
this.aliases.add("bypass");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("on/off", "flip");
|
||||
|
||||
this.permission = Permission.BYPASS.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
fme.setIsAdminBypassing(this.argAsBool(0, !fme.isAdminBypassing()));
|
||||
|
||||
// TODO: Move this to a transient field in the model??
|
||||
if (fme.isAdminBypassing()) {
|
||||
fme.msg(TL.COMMAND_BYPASS_ENABLE.toString());
|
||||
P.p.log(fme.getName() + TL.COMMAND_BYPASS_ENABLELOG.toString());
|
||||
} else {
|
||||
fme.msg(TL.COMMAND_BYPASS_DISABLE.toString());
|
||||
P.p.log(fme.getName() + TL.COMMAND_BYPASS_DISABLELOG.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_BYPASS_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.struct.ChatMode;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdChat extends FCommand {
|
||||
|
||||
public CmdChat() {
|
||||
super();
|
||||
this.aliases.add("c");
|
||||
this.aliases.add("chat");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("mode", "next");
|
||||
|
||||
this.permission = Permission.CHAT.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = true;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
if (!Conf.factionOnlyChat) {
|
||||
msg(TL.COMMAND_CHAT_DISABLED.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
String modeString = this.argAsString(0);
|
||||
ChatMode modeTarget = fme.getChatMode().getNext();
|
||||
|
||||
if (modeString != null) {
|
||||
modeString = modeString.toLowerCase();
|
||||
if (modeString.startsWith("p")) {
|
||||
modeTarget = ChatMode.PUBLIC;
|
||||
} else if (modeString.startsWith("a")) {
|
||||
modeTarget = ChatMode.ALLIANCE;
|
||||
} else if (modeString.startsWith("f")) {
|
||||
modeTarget = ChatMode.FACTION;
|
||||
} else if (modeString.startsWith("t")) {
|
||||
modeTarget = ChatMode.TRUCE;
|
||||
} else {
|
||||
msg(TL.COMMAND_CHAT_INVALIDMODE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fme.setChatMode(modeTarget);
|
||||
|
||||
if (fme.getChatMode() == ChatMode.PUBLIC) {
|
||||
msg(TL.COMMAND_CHAT_MODE_PUBLIC);
|
||||
} else if (fme.getChatMode() == ChatMode.ALLIANCE) {
|
||||
msg(TL.COMMAND_CHAT_MODE_ALLIANCE);
|
||||
} else if (fme.getChatMode() == ChatMode.TRUCE) {
|
||||
msg(TL.COMMAND_CHAT_MODE_TRUCE);
|
||||
} else {
|
||||
msg(TL.COMMAND_CHAT_MODE_FACTION);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_CHAT_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.P;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdChatSpy extends FCommand {
|
||||
|
||||
public CmdChatSpy() {
|
||||
super();
|
||||
this.aliases.add("chatspy");
|
||||
|
||||
this.optionalArgs.put("on/off", "flip");
|
||||
|
||||
this.permission = Permission.CHATSPY.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
fme.setSpyingChat(this.argAsBool(0, !fme.isSpyingChat()));
|
||||
|
||||
if (fme.isSpyingChat()) {
|
||||
fme.msg(TL.COMMAND_CHATSPY_ENABLE);
|
||||
P.p.log(fme.getName() + TL.COMMAND_CHATSPY_ENABLELOG.toString());
|
||||
} else {
|
||||
fme.msg(TL.COMMAND_CHATSPY_DISABLE);
|
||||
P.p.log(fme.getName() + TL.COMMAND_CHATSPY_DISABLELOG.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_CHATSPY_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.FLocation;
|
||||
import com.massivecraft.factions.Faction;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.util.SpiralTask;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import net.grandtheftmc.core.util.Utils;
|
||||
|
||||
|
||||
public class CmdClaim extends FCommand {
|
||||
|
||||
public CmdClaim() {
|
||||
super();
|
||||
this.aliases.add("claim");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("radius", "1");
|
||||
this.optionalArgs.put("cartel", "your");
|
||||
|
||||
this.permission = Permission.CLAIM.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
// Read and validate input
|
||||
int radius = this.argAsInt(0, 1); // Default to 1
|
||||
final Faction forFaction = this.argAsFaction(1, myFaction); // Default to own
|
||||
|
||||
if (radius < 1) {
|
||||
msg(TL.COMMAND_CLAIM_INVALIDRADIUS);
|
||||
return;
|
||||
}
|
||||
|
||||
if(me.getLocation().getWorld().getName().equals("spawn") && !this.sender.isOp()) {
|
||||
me.sendMessage(Utils.f("&c&l Cartels&8&l> &cYou cannot claim in spawn area!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (radius < 2) {
|
||||
// single chunk
|
||||
fme.attemptClaim(forFaction, me.getLocation(), true);
|
||||
} else {
|
||||
// radius claim
|
||||
if (!Permission.CLAIM_RADIUS.has(sender, false)) {
|
||||
msg(TL.COMMAND_CLAIM_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
new SpiralTask(new FLocation(me), radius) {
|
||||
private int failCount = 0;
|
||||
private final int limit = Conf.radiusClaimFailureLimit - 1;
|
||||
|
||||
@Override
|
||||
public boolean work() {
|
||||
boolean success = fme.attemptClaim(forFaction, this.currentLocation(), true);
|
||||
if (success) {
|
||||
failCount = 0;
|
||||
} else if (failCount++ >= limit) {
|
||||
this.stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_CLAIM_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.Faction;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import net.grandtheftmc.core.util.Utils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
public class CmdClaimLine extends FCommand {
|
||||
|
||||
public static final BlockFace[] axis = {BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH, BlockFace.EAST};
|
||||
|
||||
public CmdClaimLine() {
|
||||
|
||||
// Aliases
|
||||
this.aliases.add("claimline");
|
||||
this.aliases.add("cl");
|
||||
|
||||
// Args
|
||||
this.optionalArgs.put("amount", "1");
|
||||
this.optionalArgs.put("direction", "facing");
|
||||
this.optionalArgs.put("cartel", "you");
|
||||
|
||||
this.permission = Permission.CLAIM_LINE.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
// Args
|
||||
Integer amount = this.argAsInt(0, 1); // Default to 1
|
||||
|
||||
if (amount > Conf.lineClaimLimit) {
|
||||
fme.msg(TL.COMMAND_CLAIMLINE_ABOVEMAX, Conf.lineClaimLimit);
|
||||
return;
|
||||
}
|
||||
|
||||
if(me.getLocation().getWorld().getName().equals("spawn") && !this.sender.isOp()) {
|
||||
me.sendMessage(Utils.f("&c&l Cartels&8&l> &cYou cannot claim in spawn area!"));
|
||||
return;
|
||||
}
|
||||
|
||||
String direction = this.argAsString(1);
|
||||
BlockFace blockFace;
|
||||
|
||||
if (direction == null) {
|
||||
blockFace = axis[Math.round(me.getLocation().getYaw() / 90f) & 0x3];
|
||||
} else if (direction.equalsIgnoreCase("north")) {
|
||||
blockFace = BlockFace.NORTH;
|
||||
} else if (direction.equalsIgnoreCase("east")) {
|
||||
blockFace = BlockFace.EAST;
|
||||
} else if (direction.equalsIgnoreCase("south")) {
|
||||
blockFace = BlockFace.SOUTH;
|
||||
} else if (direction.equalsIgnoreCase("west")) {
|
||||
blockFace = BlockFace.WEST;
|
||||
} else {
|
||||
fme.msg(TL.COMMAND_CLAIMLINE_NOTVALID, direction);
|
||||
return;
|
||||
}
|
||||
|
||||
final Faction forFaction = this.argAsFaction(2, myFaction);
|
||||
Location location = me.getLocation();
|
||||
|
||||
// TODO: make this a task like claiming a radius?
|
||||
for (int i = 0; i < amount; i++) {
|
||||
fme.attemptClaim(forFaction, location, true);
|
||||
location = location.add(blockFace.getModX() * 16, 0, blockFace.getModZ() * 16);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_CLAIMLINE_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.P;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
public class CmdConfig extends FCommand {
|
||||
|
||||
private static HashMap<String, String> properFieldNames = new HashMap<String, String>();
|
||||
|
||||
public CmdConfig() {
|
||||
super();
|
||||
this.aliases.add("config");
|
||||
|
||||
this.requiredArgs.add("setting");
|
||||
this.requiredArgs.add("value");
|
||||
this.errorOnToManyArgs = false;
|
||||
|
||||
this.permission = Permission.CONFIG.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = false;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
// store a lookup map of lowercase field names paired with proper capitalization field names
|
||||
// that way, if the person using this command messes up the capitalization, we can fix that
|
||||
if (properFieldNames.isEmpty()) {
|
||||
Field[] fields = Conf.class.getDeclaredFields();
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
properFieldNames.put(fields[i].getName().toLowerCase(), fields[i].getName());
|
||||
}
|
||||
}
|
||||
|
||||
String field = this.argAsString(0).toLowerCase();
|
||||
if (field.startsWith("\"") && field.endsWith("\"")) {
|
||||
field = field.substring(1, field.length() - 1);
|
||||
}
|
||||
String fieldName = properFieldNames.get(field);
|
||||
|
||||
if (fieldName == null || fieldName.isEmpty()) {
|
||||
msg(TL.COMMAND_CONFIG_NOEXIST, field);
|
||||
return;
|
||||
}
|
||||
|
||||
String success;
|
||||
|
||||
String value = args.get(1);
|
||||
for (int i = 2; i < args.size(); i++) {
|
||||
value += ' ' + args.get(i);
|
||||
}
|
||||
|
||||
try {
|
||||
Field target = Conf.class.getField(fieldName);
|
||||
|
||||
// boolean
|
||||
if (target.getType() == boolean.class) {
|
||||
boolean targetValue = this.strAsBool(value);
|
||||
target.setBoolean(null, targetValue);
|
||||
|
||||
if (targetValue) {
|
||||
success = "\"" + fieldName + TL.COMMAND_CONFIG_SET_TRUE.toString();
|
||||
} else {
|
||||
success = "\"" + fieldName + TL.COMMAND_CONFIG_SET_FALSE.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// int
|
||||
else if (target.getType() == int.class) {
|
||||
try {
|
||||
int intVal = Integer.parseInt(value);
|
||||
target.setInt(null, intVal);
|
||||
success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + intVal + ".";
|
||||
} catch (NumberFormatException ex) {
|
||||
sendMessage(TL.COMMAND_CONFIG_INTREQUIRED.format(fieldName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// long
|
||||
else if (target.getType() == long.class) {
|
||||
try {
|
||||
long longVal = Long.parseLong(value);
|
||||
target.setLong(null, longVal);
|
||||
success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + longVal + ".";
|
||||
} catch (NumberFormatException ex) {
|
||||
sendMessage(TL.COMMAND_CONFIG_LONGREQUIRED.format(fieldName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// double
|
||||
else if (target.getType() == double.class) {
|
||||
try {
|
||||
double doubleVal = Double.parseDouble(value);
|
||||
target.setDouble(null, doubleVal);
|
||||
success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + doubleVal + ".";
|
||||
} catch (NumberFormatException ex) {
|
||||
sendMessage(TL.COMMAND_CONFIG_DOUBLEREQUIRED.format(fieldName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// float
|
||||
else if (target.getType() == float.class) {
|
||||
try {
|
||||
float floatVal = Float.parseFloat(value);
|
||||
target.setFloat(null, floatVal);
|
||||
success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + floatVal + ".";
|
||||
} catch (NumberFormatException ex) {
|
||||
sendMessage(TL.COMMAND_CONFIG_FLOATREQUIRED.format(fieldName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// String
|
||||
else if (target.getType() == String.class) {
|
||||
target.set(null, value);
|
||||
success = "\"" + fieldName + TL.COMMAND_CONFIG_OPTIONSET.toString() + value + "\".";
|
||||
}
|
||||
|
||||
// ChatColor
|
||||
else if (target.getType() == ChatColor.class) {
|
||||
ChatColor newColor = null;
|
||||
try {
|
||||
newColor = ChatColor.valueOf(value.toUpperCase());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
|
||||
}
|
||||
if (newColor == null) {
|
||||
sendMessage(TL.COMMAND_CONFIG_INVALID_COLOUR.format(fieldName, value.toUpperCase()));
|
||||
return;
|
||||
}
|
||||
target.set(null, newColor);
|
||||
success = "\"" + fieldName + TL.COMMAND_CONFIG_COLOURSET.toString() + value.toUpperCase() + "\".";
|
||||
}
|
||||
|
||||
// Set<?> or other parameterized collection
|
||||
else if (target.getGenericType() instanceof ParameterizedType) {
|
||||
ParameterizedType targSet = (ParameterizedType) target.getGenericType();
|
||||
Type innerType = targSet.getActualTypeArguments()[0];
|
||||
|
||||
// not a Set, somehow, and that should be the only collection we're using in Conf.java
|
||||
if (targSet.getRawType() != Set.class) {
|
||||
sendMessage(TL.COMMAND_CONFIG_INVALID_COLLECTION.format(fieldName));
|
||||
return;
|
||||
}
|
||||
|
||||
// Set<Material>
|
||||
else if (innerType == Material.class) {
|
||||
Material newMat = null;
|
||||
try {
|
||||
newMat = Material.valueOf(value.toUpperCase());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
|
||||
}
|
||||
if (newMat == null) {
|
||||
sendMessage(TL.COMMAND_CONFIG_INVALID_MATERIAL.format(fieldName, value.toUpperCase()));
|
||||
return;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") Set<Material> matSet = (Set<Material>) target.get(null);
|
||||
|
||||
// Material already present, so remove it
|
||||
if (matSet.contains(newMat)) {
|
||||
matSet.remove(newMat);
|
||||
target.set(null, matSet);
|
||||
success = TL.COMMAND_CONFIG_MATERIAL_REMOVED.format(fieldName, value.toUpperCase());
|
||||
}
|
||||
// Material not present yet, add it
|
||||
else {
|
||||
matSet.add(newMat);
|
||||
target.set(null, matSet);
|
||||
success = TL.COMMAND_CONFIG_MATERIAL_ADDED.format(fieldName, value.toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
// Set<String>
|
||||
else if (innerType == String.class) {
|
||||
@SuppressWarnings("unchecked") Set<String> stringSet = (Set<String>) target.get(null);
|
||||
|
||||
// String already present, so remove it
|
||||
if (stringSet.contains(value)) {
|
||||
stringSet.remove(value);
|
||||
target.set(null, stringSet);
|
||||
success = TL.COMMAND_CONFIG_SET_REMOVED.format(fieldName, value);
|
||||
}
|
||||
// String not present yet, add it
|
||||
else {
|
||||
stringSet.add(value);
|
||||
target.set(null, stringSet);
|
||||
success = TL.COMMAND_CONFIG_SET_ADDED.format(fieldName, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Set of unknown type
|
||||
else {
|
||||
sendMessage(TL.COMMAND_CONFIG_INVALID_TYPESET.format(fieldName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// unknown type
|
||||
else {
|
||||
sendMessage(TL.COMMAND_CONFIG_ERROR_TYPE.format(fieldName, target.getClass().getName()));
|
||||
return;
|
||||
}
|
||||
} catch (NoSuchFieldException ex) {
|
||||
sendMessage(TL.COMMAND_CONFIG_ERROR_MATCHING.format(fieldName));
|
||||
return;
|
||||
} catch (IllegalAccessException ex) {
|
||||
sendMessage(TL.COMMAND_CONFIG_ERROR_SETTING.format(fieldName, value));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!success.isEmpty()) {
|
||||
if (sender instanceof Player) {
|
||||
sendMessage(success);
|
||||
P.p.log(success + TL.COMMAND_CONFIG_LOG.format((Player) sender));
|
||||
} else // using P.p.log() instead of sendMessage if run from server console so that "[Factions v#.#.#]" is prepended in server log
|
||||
{
|
||||
P.p.log(success);
|
||||
}
|
||||
}
|
||||
// save change to disk
|
||||
Conf.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_CONFIG_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.Conf.Backend;
|
||||
import com.massivecraft.factions.zcore.persist.json.FactionsJSON;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
|
||||
public class CmdConvert extends FCommand {
|
||||
|
||||
public CmdConvert() {
|
||||
this.aliases.add("convert");
|
||||
|
||||
this.requiredArgs.add("[MYSQL|JSON]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
if (!(this.sender instanceof ConsoleCommandSender)) {
|
||||
this.sender.sendMessage(TL.GENERIC_CONSOLEONLY.toString());
|
||||
}
|
||||
Backend nb = Backend.valueOf(this.argAsString(0).toUpperCase());
|
||||
if (nb == Conf.backEnd) {
|
||||
this.sender.sendMessage(TL.COMMAND_CONVERT_BACKEND_RUNNING.toString());
|
||||
return;
|
||||
}
|
||||
switch (nb) {
|
||||
case JSON:
|
||||
FactionsJSON.convertTo();
|
||||
break;
|
||||
default:
|
||||
this.sender.sendMessage(TL.COMMAND_CONVERT_BACKEND_INVALID.toString());
|
||||
return;
|
||||
|
||||
}
|
||||
Conf.backEnd = nb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_CONVERT_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.*;
|
||||
import com.massivecraft.factions.event.FPlayerJoinEvent;
|
||||
import com.massivecraft.factions.event.FactionCreateEvent;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.struct.Role;
|
||||
import com.massivecraft.factions.util.MiscUtil;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import net.grandtheftmc.core.util.Utils;
|
||||
import net.grandtheftmc.core.util.NumeralUtil;
|
||||
import net.grandtheftmc.vice.Vice;
|
||||
import net.grandtheftmc.vice.users.ViceUser;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
public class CmdCreate extends FCommand {
|
||||
|
||||
public CmdCreate() {
|
||||
super();
|
||||
this.aliases.add("create");
|
||||
|
||||
this.requiredArgs.add("cartel tag");
|
||||
//this.optionalArgs.put("", "");
|
||||
|
||||
this.permission = Permission.CREATE.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
String tag = this.argAsString(0);
|
||||
|
||||
if (fme.hasFaction()) {
|
||||
msg(TL.COMMAND_CREATE_MUSTLEAVE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Factions.getInstance().isTagTaken(tag)) {
|
||||
msg(TL.COMMAND_CREATE_INUSE);
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<String> tagValidationErrors = MiscUtil.validateTag(tag);
|
||||
if (tagValidationErrors.size() > 0) {
|
||||
sendMessage(tagValidationErrors);
|
||||
return;
|
||||
}
|
||||
|
||||
// if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay
|
||||
// if (!canAffordCommand(Conf.econCostCreate, TL.COMMAND_CREATE_TOCREATE.toString())) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
if(Conf.econCostCreate > 0) {
|
||||
if (fme.getPlayer() == null) return;
|
||||
ViceUser user = Vice.getUserManager().getLoadedUser(fme.getPlayer().getUniqueId());
|
||||
if (user == null) return;
|
||||
if (!user.hasMoney(Conf.econCostCreate)) {
|
||||
msg("you can't afford <h>%s<i> %s.", NumeralUtil.toCurrency(Conf.econCostCreate, Locale.US), TL.COMMAND_CREATE_TOCREATE.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
user.takeMoney(Conf.econCostCreate);
|
||||
sender.sendMessage(Utils.f("&c- " + NumeralUtil.toCurrency(Conf.econCostCreate, Locale.US)));
|
||||
}
|
||||
|
||||
// trigger the faction creation event (cancellable)
|
||||
FactionCreateEvent createEvent = new FactionCreateEvent(me, tag);
|
||||
Bukkit.getServer().getPluginManager().callEvent(createEvent);
|
||||
if (createEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// then make 'em pay (if applicable)
|
||||
// if (!payForCommand(Conf.econCostCreate, TL.COMMAND_CREATE_TOCREATE, TL.COMMAND_CREATE_FORCREATE)) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
Faction faction = Factions.getInstance().createFaction();
|
||||
|
||||
// TODO: Why would this even happen??? Auto increment clash??
|
||||
if (faction == null) {
|
||||
msg(TL.COMMAND_CREATE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// finish setting up the Faction
|
||||
faction.setTag(tag);
|
||||
|
||||
// trigger the faction join event for the creator
|
||||
FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.CREATE);
|
||||
Bukkit.getServer().getPluginManager().callEvent(joinEvent);
|
||||
// join event cannot be cancelled or you'll have an empty faction
|
||||
|
||||
// finish setting up the FPlayer
|
||||
fme.setRole(Role.ADMIN);
|
||||
fme.setFaction(faction);
|
||||
|
||||
for (FPlayer follower : FPlayers.getInstance().getOnlinePlayers()) {
|
||||
follower.msg(TL.COMMAND_CREATE_CREATED, fme.describeTo(follower, true), faction.getTag(follower));
|
||||
}
|
||||
|
||||
msg(TL.COMMAND_CREATE_YOUSHOULD, p.cmdBase.cmdDescription.getUseageTemplate());
|
||||
|
||||
if (Conf.logFactionCreate) {
|
||||
P.p.log(fme.getName() + TL.COMMAND_CREATE_CREATEDLOG.toString() + tag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_CREATE_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.FPlayers;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import mkremins.fanciful.FancyMessage;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public class CmdDeinvite extends FCommand {
|
||||
|
||||
public CmdDeinvite() {
|
||||
super();
|
||||
this.aliases.add("deinvite");
|
||||
this.aliases.add("deinv");
|
||||
|
||||
this.optionalArgs.put("player name", "name");
|
||||
//this.optionalArgs.put("", "");
|
||||
|
||||
this.permission = Permission.DEINVITE.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = true;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
FPlayer you = this.argAsBestFPlayerMatch(0);
|
||||
if (you == null) {
|
||||
FancyMessage msg = new FancyMessage(TL.COMMAND_DEINVITE_CANDEINVITE.toString()).color(ChatColor.GOLD);
|
||||
for (String id : myFaction.getInvites()) {
|
||||
FPlayer fp = FPlayers.getInstance().getById(id);
|
||||
String name = fp != null ? fp.getName() : id;
|
||||
msg.then(name + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_DEINVITE_CLICKTODEINVITE.format(name)).command("/" + Conf.baseCommandAliases.get(0) + " deinvite " + name);
|
||||
}
|
||||
sendFancyMessage(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (you.getFaction() == myFaction) {
|
||||
msg(TL.COMMAND_DEINVITE_ALREADYMEMBER, you.getName(), myFaction.getTag());
|
||||
msg(TL.COMMAND_DEINVITE_MIGHTWANT, p.cmdBase.cmdKick.getUseageTemplate(false));
|
||||
return;
|
||||
}
|
||||
|
||||
myFaction.deinvite(you);
|
||||
|
||||
you.msg(TL.COMMAND_DEINVITE_REVOKED, fme.describeTo(you), myFaction.describeTo(you));
|
||||
|
||||
myFaction.msg(TL.COMMAND_DEINVITE_REVOKES, fme.describeTo(myFaction), you.describeTo(myFaction));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_DEINVITE_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.P;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdDelFWarp extends FCommand {
|
||||
|
||||
public CmdDelFWarp() {
|
||||
super();
|
||||
this.aliases.add("delwarp");
|
||||
this.aliases.add("dw");
|
||||
this.aliases.add("deletewarp");
|
||||
this.requiredArgs.add("warp name");
|
||||
this.senderMustBeMember = true;
|
||||
this.senderMustBeModerator = true;
|
||||
this.senderMustBePlayer = true;
|
||||
this.permission = Permission.SETWARP.node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
String warp = argAsString(0);
|
||||
if (myFaction.isWarp(warp)) {
|
||||
if (!transact(fme)) {
|
||||
return;
|
||||
}
|
||||
myFaction.removeWarp(warp);
|
||||
fme.msg(TL.COMMAND_DELFWARP_DELETED, warp);
|
||||
} else {
|
||||
fme.msg(TL.COMMAND_DELFWARP_INVALID, warp);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean transact(FPlayer player) {
|
||||
return !P.p.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(P.p.getConfig().getDouble("warp-cost.delwarp", 5), TL.COMMAND_DELFWARP_TODELETE.toString(), TL.COMMAND_DELFWARP_FORDELETE.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_DELFWARP_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.FPlayers;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import com.massivecraft.factions.zcore.util.TextUtil;
|
||||
|
||||
public class CmdDescription extends FCommand {
|
||||
|
||||
public CmdDescription() {
|
||||
super();
|
||||
this.aliases.add("desc");
|
||||
this.aliases.add("description");
|
||||
|
||||
this.requiredArgs.add("desc");
|
||||
this.errorOnToManyArgs = false;
|
||||
//this.optionalArgs
|
||||
|
||||
this.permission = Permission.DESCRIPTION.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = true;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
// if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay
|
||||
if (!payForCommand(Conf.econCostDesc, TL.COMMAND_DESCRIPTION_TOCHANGE, TL.COMMAND_DESCRIPTION_FORCHANGE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// since "&" color tags seem to work even through plain old FPlayer.sendMessage() for some reason, we need to break those up
|
||||
// And replace all the % because it messes with string formatting and this is easy way around that.
|
||||
myFaction.setDescription(TextUtil.implode(args, " ").replaceAll("%", "").replaceAll("(&([a-f0-9klmnor]))", "& $2"));
|
||||
|
||||
if (!Conf.broadcastDescriptionChanges) {
|
||||
fme.msg(TL.COMMAND_DESCRIPTION_CHANGED, myFaction.describeTo(fme));
|
||||
fme.sendMessage(myFaction.getDescription());
|
||||
return;
|
||||
}
|
||||
|
||||
// Broadcast the description to everyone
|
||||
for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) {
|
||||
fplayer.msg(TL.COMMAND_DESCRIPTION_CHANGES, myFaction.describeTo(fplayer));
|
||||
fplayer.sendMessage(myFaction.getDescription()); // players can inject "&" or "`" or "<i>" or whatever in their description; &k is particularly interesting looking
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_DESCRIPTION_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.*;
|
||||
import com.massivecraft.factions.event.FPlayerLeaveEvent;
|
||||
import com.massivecraft.factions.event.FactionDisbandEvent;
|
||||
import com.massivecraft.factions.integration.Econ;
|
||||
import com.massivecraft.factions.scoreboards.FTeamWrapper;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.struct.Role;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
|
||||
public class CmdDisband extends FCommand {
|
||||
|
||||
public CmdDisband() {
|
||||
super();
|
||||
this.aliases.add("disband");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("cartel tag", "yours");
|
||||
|
||||
this.permission = Permission.DISBAND.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = false;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
// The faction, default to your own.. but null if console sender.
|
||||
Faction faction = this.argAsFaction(0, fme == null ? null : myFaction);
|
||||
if (faction == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isMyFaction = fme == null ? false : faction == myFaction;
|
||||
|
||||
if (isMyFaction) {
|
||||
if (!assertMinRole(Role.ADMIN)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!Permission.DISBAND_ANY.has(sender, true)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!faction.isNormal()) {
|
||||
msg(TL.COMMAND_DISBAND_IMMUTABLE.toString());
|
||||
return;
|
||||
}
|
||||
if (faction.isPermanent()) {
|
||||
msg(TL.COMMAND_DISBAND_MARKEDPERMANENT.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
FactionDisbandEvent disbandEvent = new FactionDisbandEvent(me, faction.getId());
|
||||
Bukkit.getServer().getPluginManager().callEvent(disbandEvent);
|
||||
if (disbandEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send FPlayerLeaveEvent for each player in the faction
|
||||
for (FPlayer fplayer : faction.getFPlayers()) {
|
||||
Bukkit.getServer().getPluginManager().callEvent(new FPlayerLeaveEvent(fplayer, faction, FPlayerLeaveEvent.PlayerLeaveReason.DISBAND));
|
||||
}
|
||||
|
||||
// Inform all players
|
||||
for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) {
|
||||
String who = senderIsConsole ? TL.GENERIC_SERVERADMIN.toString() : fme.describeTo(fplayer);
|
||||
if (fplayer.getFaction() == faction) {
|
||||
fplayer.msg(TL.COMMAND_DISBAND_BROADCAST_YOURS, who);
|
||||
} else {
|
||||
fplayer.msg(TL.COMMAND_DISBAND_BROADCAST_NOTYOURS, who, faction.getTag(fplayer));
|
||||
}
|
||||
}
|
||||
if (Conf.logFactionDisband) {
|
||||
//TODO: Format this correctly and translate.
|
||||
P.p.log("The cartel " + faction.getTag() + " (" + faction.getId() + ") was disbanded by " + (senderIsConsole ? "console command" : fme.getName()) + ".");
|
||||
}
|
||||
|
||||
if (Econ.shouldBeUsed() && !senderIsConsole) {
|
||||
//Give all the faction's money to the disbander
|
||||
double amount = Econ.getBalance(faction.getAccountId());
|
||||
Econ.transferMoney(fme, faction, fme, amount, false);
|
||||
|
||||
if (amount > 0.0) {
|
||||
String amountString = Econ.moneyString(amount);
|
||||
msg(TL.COMMAND_DISBAND_HOLDINGS, amountString);
|
||||
//TODO: Format this correctly and translate
|
||||
P.p.log(fme.getName() + " has been given bank holdings of " + amountString + " from disbanding " + faction.getTag() + ".");
|
||||
}
|
||||
}
|
||||
|
||||
Factions.getInstance().removeFaction(faction.getId());
|
||||
FTeamWrapper.applyUpdates(faction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_DISBAND_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.P;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.util.LazyLocation;
|
||||
import com.massivecraft.factions.util.WarmUpUtil;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import mkremins.fanciful.FancyMessage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class CmdFWarp extends FCommand {
|
||||
|
||||
public CmdFWarp() {
|
||||
super();
|
||||
this.aliases.add("warp");
|
||||
this.aliases.add("warps");
|
||||
this.optionalArgs.put("warpname", "warpname");
|
||||
|
||||
this.permission = Permission.WARP.node;
|
||||
this.senderMustBeMember = true;
|
||||
this.senderMustBeModerator = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
//TODO: check if in combat.
|
||||
if (args.size() == 0) {
|
||||
FancyMessage msg = new FancyMessage(TL.COMMAND_FWARP_WARPS.toString()).color(ChatColor.GOLD);
|
||||
Map<String, LazyLocation> warps = myFaction.getWarps();
|
||||
for (String s : warps.keySet()) {
|
||||
msg.then(s + " ").tooltip(TL.COMMAND_FWARP_CLICKTOWARP.toString()).command("/" + Conf.baseCommandAliases.get(0) + " warp " + s).color(ChatColor.WHITE);
|
||||
}
|
||||
sendFancyMessage(msg);
|
||||
} else if (args.size() > 1) {
|
||||
fme.msg(TL.COMMAND_FWARP_COMMANDFORMAT);
|
||||
} else {
|
||||
final String warpName = argAsString(0);
|
||||
if (myFaction.isWarp(argAsString(0))) {
|
||||
if (!transact(fme)) {
|
||||
return;
|
||||
}
|
||||
final FPlayer fPlayer = fme;
|
||||
final UUID uuid = fme.getPlayer().getUniqueId();
|
||||
this.doWarmUp(WarmUpUtil.Warmup.WARP, TL.WARMUPS_NOTIFY_TELEPORT, warpName, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null) {
|
||||
player.teleport(fPlayer.getFaction().getWarp(warpName).getLocation());
|
||||
fPlayer.msg(TL.COMMAND_FWARP_WARPED, warpName);
|
||||
}
|
||||
}
|
||||
}, this.p.getConfig().getLong("warmups.f-warp", 0));
|
||||
} else {
|
||||
fme.msg(TL.COMMAND_FWARP_INVALID, warpName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean transact(FPlayer player) {
|
||||
return !P.p.getConfig().getBoolean("warp-cost.enabled", false) || player.isAdminBypassing() || payForCommand(P.p.getConfig().getDouble("warp-cost.warp", 5), TL.COMMAND_FWARP_TOWARP.toString(), TL.COMMAND_FWARP_FORWARPING.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_FWARP_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.P;
|
||||
import com.massivecraft.factions.integration.Econ;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class CmdHelp extends FCommand {
|
||||
|
||||
public CmdHelp() {
|
||||
super();
|
||||
this.aliases.add("help");
|
||||
this.aliases.add("h");
|
||||
this.aliases.add("?");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("page", "1");
|
||||
|
||||
this.permission = Permission.HELP.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = false;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
if (P.p.getConfig().getBoolean("use-old-help", true)) {
|
||||
if (helpPages == null) {
|
||||
updateHelp();
|
||||
}
|
||||
|
||||
int page = this.argAsInt(0, 1);
|
||||
sendMessage(p.txt.titleize("Cartels Help (" + page + "/" + helpPages.size() + ")"));
|
||||
|
||||
page -= 1;
|
||||
|
||||
if (page < 0 || page >= helpPages.size()) {
|
||||
msg(TL.COMMAND_HELP_404.format(String.valueOf(page)));
|
||||
return;
|
||||
}
|
||||
sendMessage(helpPages.get(page));
|
||||
return;
|
||||
}
|
||||
ConfigurationSection help = P.p.getConfig().getConfigurationSection("help");
|
||||
if (help == null) {
|
||||
help = P.p.getConfig().createSection("help"); // create new help section
|
||||
List<String> error = new ArrayList<String>();
|
||||
error.add("&cUpdate help messages in config.yml!");
|
||||
error.add("&cSet use-old-help for legacy help messages");
|
||||
help.set("'1'", error); // add default error messages
|
||||
}
|
||||
String pageArg = this.argAsString(0, "1");
|
||||
List<String> page = help.getStringList(pageArg);
|
||||
if (page == null || page.isEmpty()) {
|
||||
msg(TL.COMMAND_HELP_404.format(pageArg));
|
||||
return;
|
||||
}
|
||||
for (String helpLine : page) {
|
||||
sendMessage(P.p.txt.parse(helpLine));
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------//
|
||||
// Build the help pages
|
||||
//----------------------------------------------//
|
||||
|
||||
public ArrayList<ArrayList<String>> helpPages;
|
||||
|
||||
public void updateHelp() {
|
||||
helpPages = new ArrayList<ArrayList<String>>();
|
||||
ArrayList<String> pageLines;
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add(p.cmdBase.cmdHelp.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdList.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdShow.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdPower.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdJoin.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdLeave.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdChat.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdToggleAllianceChat.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdHome.getUseageTemplate(true));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_NEXTCREATE.toString()));
|
||||
helpPages.add(pageLines);
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add(p.cmdBase.cmdCreate.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdDescription.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdTag.getUseageTemplate(true));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_INVITATIONS.toString()));
|
||||
pageLines.add(p.cmdBase.cmdOpen.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdInvite.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdDeinvite.getUseageTemplate(true));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_HOME.toString()));
|
||||
pageLines.add(p.cmdBase.cmdSethome.getUseageTemplate(true));
|
||||
helpPages.add(pageLines);
|
||||
|
||||
if (Econ.isSetup() && Conf.econEnabled && Conf.bankEnabled) {
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add("");
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_1.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_2.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_BANK_3.toString()));
|
||||
pageLines.add("");
|
||||
pageLines.add(p.cmdBase.cmdMoney.getUseageTemplate(true));
|
||||
pageLines.add("");
|
||||
pageLines.add("");
|
||||
pageLines.add("");
|
||||
helpPages.add(pageLines);
|
||||
}
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add(p.cmdBase.cmdClaim.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdAutoClaim.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdUnclaim.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdUnclaimall.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdKick.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdMod.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdAdmin.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdTitle.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdSB.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdSeeChunk.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdStatus.getUseageTemplate(true));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_PLAYERTITLES.toString()));
|
||||
helpPages.add(pageLines);
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add(p.cmdBase.cmdMap.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdBoom.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdOwner.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdOwnerList.getUseageTemplate(true));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_1.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_2.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_OWNERSHIP_3.toString()));
|
||||
helpPages.add(pageLines);
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add(p.cmdBase.cmdDisband.getUseageTemplate(true));
|
||||
pageLines.add("");
|
||||
pageLines.add(p.cmdBase.cmdRelationAlly.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdRelationNeutral.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdRelationEnemy.getUseageTemplate(true));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_1.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_2.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_3.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_4.toString()));
|
||||
helpPages.add(pageLines);
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_5.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_6.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_7.toString()));
|
||||
pageLines.add(TL.COMMAND_HELP_RELATIONS_8.toString());
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_9.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_10.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_11.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_12.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_RELATIONS_13.toString()));
|
||||
helpPages.add(pageLines);
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_1.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_2.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_3.toString()));
|
||||
pageLines.add(TL.COMMAND_HELP_PERMISSIONS_4.toString());
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_5.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_6.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_7.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_8.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_PERMISSIONS_9.toString()));
|
||||
helpPages.add(pageLines);
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add(TL.COMMAND_HELP_MOAR_1.toString());
|
||||
pageLines.add(p.cmdBase.cmdBypass.getUseageTemplate(true));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_1.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_2.toString()));
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_ADMIN_3.toString()));
|
||||
pageLines.add(p.cmdBase.cmdSafeunclaimall.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdWarunclaimall.getUseageTemplate(true));
|
||||
//TODO:TL
|
||||
pageLines.add(p.txt.parse("<i>Note: " + p.cmdBase.cmdUnclaim.getUseageTemplate(false) + P.p.txt.parse("<i>") + " works on safe/war zones as well."));
|
||||
pageLines.add(p.cmdBase.cmdPeaceful.getUseageTemplate(true));
|
||||
helpPages.add(pageLines);
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_MOAR_2.toString()));
|
||||
pageLines.add(p.cmdBase.cmdChatSpy.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdPermanent.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdPermanentPower.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdPowerBoost.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdConfig.getUseageTemplate(true));
|
||||
helpPages.add(pageLines);
|
||||
|
||||
pageLines = new ArrayList<String>();
|
||||
pageLines.add(p.txt.parse(TL.COMMAND_HELP_MOAR_3.toString()));
|
||||
pageLines.add(p.cmdBase.cmdLock.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdReload.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdSaveAll.getUseageTemplate(true));
|
||||
pageLines.add(p.cmdBase.cmdVersion.getUseageTemplate(true));
|
||||
helpPages.add(pageLines);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_HELP_DESCRIPTION;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.*;
|
||||
import com.massivecraft.factions.integration.Essentials;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.struct.Relation;
|
||||
import com.massivecraft.factions.struct.Role;
|
||||
import com.massivecraft.factions.util.WarmUpUtil;
|
||||
import com.massivecraft.factions.zcore.util.SmokeUtil;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class CmdHome extends FCommand {
|
||||
|
||||
public CmdHome() {
|
||||
super();
|
||||
this.aliases.add("home");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
//this.optionalArgs.put("", "");
|
||||
|
||||
this.permission = Permission.HOME.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = true;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
// TODO: Hide this command on help also.
|
||||
if (!Conf.homesEnabled) {
|
||||
fme.msg(TL.COMMAND_HOME_DISABLED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Conf.homesTeleportCommandEnabled) {
|
||||
fme.msg(TL.COMMAND_HOME_TELEPORTDISABLED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!myFaction.hasHome()) {
|
||||
fme.msg(TL.COMMAND_HOME_NOHOME.toString() + (fme.getRole().value < Role.MODERATOR.value ? TL.GENERIC_ASKYOURLEADER.toString() : TL.GENERIC_YOUSHOULD.toString()));
|
||||
fme.sendMessage(p.cmdBase.cmdSethome.getUseageTemplate());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Conf.homesTeleportAllowedFromEnemyTerritory && fme.isInEnemyTerritory()) {
|
||||
fme.msg(TL.COMMAND_HOME_INENEMY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Conf.homesTeleportAllowedFromDifferentWorld && me.getWorld().getUID() != myFaction.getHome().getWorld().getUID()) {
|
||||
fme.msg(TL.COMMAND_HOME_WRONGWORLD);
|
||||
return;
|
||||
}
|
||||
|
||||
Faction faction = Board.getInstance().getFactionAt(new FLocation(me.getLocation()));
|
||||
final Location loc = me.getLocation().clone();
|
||||
|
||||
// if player is not in a safe zone or their own faction territory, only allow teleport if no enemies are nearby
|
||||
if (Conf.homesTeleportAllowedEnemyDistance > 0 &&
|
||||
!faction.isSafeZone() &&
|
||||
(!fme.isInOwnTerritory() || (fme.isInOwnTerritory() && !Conf.homesTeleportIgnoreEnemiesIfInOwnTerritory))) {
|
||||
World w = loc.getWorld();
|
||||
double x = loc.getX();
|
||||
double y = loc.getY();
|
||||
double z = loc.getZ();
|
||||
|
||||
for (Player p : me.getServer().getOnlinePlayers()) {
|
||||
if (p == null || !p.isOnline() || p.isDead() || p == me || p.getWorld() != w) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FPlayer fp = FPlayers.getInstance().getByPlayer(p);
|
||||
if (fme.getRelationTo(fp) != Relation.ENEMY || fp.isVanished()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Location l = p.getLocation();
|
||||
double dx = Math.abs(x - l.getX());
|
||||
double dy = Math.abs(y - l.getY());
|
||||
double dz = Math.abs(z - l.getZ());
|
||||
double max = Conf.homesTeleportAllowedEnemyDistance;
|
||||
|
||||
// box-shaped distance check
|
||||
if (dx > max || dy > max || dz > max) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fme.msg(TL.COMMAND_HOME_ENEMYNEAR, String.valueOf(Conf.homesTeleportAllowedEnemyDistance));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay
|
||||
if (!payForCommand(Conf.econCostHome, TL.COMMAND_HOME_TOTELEPORT.toString(), TL.COMMAND_HOME_FORTELEPORT.toString())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if Essentials teleport handling is enabled and available, pass the teleport off to it (for delay and cooldown)
|
||||
if (Essentials.handleTeleport(me, myFaction.getHome())) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.doWarmUp(WarmUpUtil.Warmup.HOME, TL.WARMUPS_NOTIFY_TELEPORT, "Home", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Create a smoke effect
|
||||
if (Conf.homesTeleportCommandSmokeEffectEnabled) {
|
||||
List<Location> smokeLocations = new ArrayList<Location>();
|
||||
smokeLocations.add(loc);
|
||||
smokeLocations.add(loc.add(0, 1, 0));
|
||||
smokeLocations.add(CmdHome.this.myFaction.getHome());
|
||||
smokeLocations.add(CmdHome.this.myFaction.getHome().clone().add(0, 1, 0));
|
||||
SmokeUtil.spawnCloudRandom(smokeLocations, Conf.homesTeleportCommandSmokeEffectThickness);
|
||||
}
|
||||
|
||||
CmdHome.this.me.teleport(CmdHome.this.myFaction.getHome());
|
||||
}
|
||||
}, this.p.getConfig().getLong("warmups.f-home", 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_HOME_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.eco.EcoResult;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import mkremins.fanciful.FancyMessage;
|
||||
import net.grandtheftmc.core.util.NumeralUtil;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class CmdInvite extends FCommand {
|
||||
|
||||
public CmdInvite() {
|
||||
super();
|
||||
this.aliases.add("invite");
|
||||
this.aliases.add("inv");
|
||||
|
||||
this.requiredArgs.add("player name");
|
||||
//this.optionalArgs.put("", "");
|
||||
|
||||
this.permission = Permission.INVITE.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = true;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
FPlayer you = this.argAsBestFPlayerMatch(0);
|
||||
if (you == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (you.getFaction() == myFaction) {
|
||||
msg(TL.COMMAND_INVITE_ALREADYMEMBER, you.getName(), myFaction.getTag());
|
||||
msg(TL.GENERIC_YOUMAYWANT.toString() + p.cmdBase.cmdKick.getUseageTemplate(false));
|
||||
return;
|
||||
}
|
||||
|
||||
// if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay
|
||||
// if (!payForCommand(Conf.econCostInvite, TL.COMMAND_INVITE_TOINVITE.toString(), TL.COMMAND_INVITE_FORINVITE.toString())) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
if(Conf.econCostInvite > 0) {
|
||||
EcoResult result = myFaction.takeFromStash(Conf.econCostInvite);
|
||||
if(result == EcoResult.LOW_FUNDS) {
|
||||
fme.msg("<h>%s<i> can't afford <h>%s<i> %s.", myFaction.describeTo(myFaction, true), NumeralUtil.toCurrency(Conf.econCostInvite, Locale.US), TL.COMMAND_INVITE_TOINVITE);
|
||||
return;
|
||||
}
|
||||
|
||||
if(result != EcoResult.SUCCESS) return;
|
||||
}
|
||||
|
||||
myFaction.invite(you);
|
||||
if (!you.isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Tooltips, colors, and commands only apply to the string immediately before it.
|
||||
FancyMessage message = new FancyMessage(fme.describeTo(you, true)).tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()).command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()).then(TL.COMMAND_INVITE_INVITEDYOU.toString()).color(ChatColor.YELLOW).tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()).command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag()).then(myFaction.describeTo(you)).tooltip(TL.COMMAND_INVITE_CLICKTOJOIN.toString()).command("/" + Conf.baseCommandAliases.get(0) + " join " + myFaction.getTag());
|
||||
|
||||
message.send(you.getPlayer());
|
||||
|
||||
//you.msg("%s<i> invited you to %s", fme.describeTo(you, true), myFaction.describeTo(you));
|
||||
myFaction.msg(TL.COMMAND_INVITE_INVITED, fme.describeTo(myFaction, true), you.describeTo(myFaction));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_INVITE_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.*;
|
||||
import com.massivecraft.factions.event.FPlayerJoinEvent;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class CmdJoin extends FCommand {
|
||||
|
||||
public CmdJoin() {
|
||||
super();
|
||||
this.aliases.add("join");
|
||||
|
||||
this.requiredArgs.add("cartel name");
|
||||
this.optionalArgs.put("player", "you");
|
||||
|
||||
this.permission = Permission.JOIN.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
Faction faction = this.argAsFaction(0);
|
||||
if (faction == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FPlayer fplayer = this.argAsBestFPlayerMatch(1, fme, false);
|
||||
boolean samePlayer = fplayer == fme;
|
||||
|
||||
if (!samePlayer && !Permission.JOIN_OTHERS.has(sender, false)) {
|
||||
msg(TL.COMMAND_JOIN_CANNOTFORCE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!faction.isNormal()) {
|
||||
msg(TL.COMMAND_JOIN_SYSTEMFACTION);
|
||||
return;
|
||||
}
|
||||
|
||||
if (faction == fplayer.getFaction()) {
|
||||
//TODO:TL
|
||||
msg(TL.COMMAND_JOIN_ALREADYMEMBER, fplayer.describeTo(fme, true), (samePlayer ? "are" : "is"), faction.getTag(fme));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Conf.factionMemberLimit > 0 && faction.getFPlayers().size() >= Conf.factionMemberLimit) {
|
||||
msg(TL.COMMAND_JOIN_ATLIMIT, faction.getTag(fme), Conf.factionMemberLimit, fplayer.describeTo(fme, false));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fplayer.hasFaction()) {
|
||||
//TODO:TL
|
||||
msg(TL.COMMAND_JOIN_INOTHERFACTION, fplayer.describeTo(fme, true), (samePlayer ? "your" : "their"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Conf.canLeaveWithNegativePower && fplayer.getPower() < 0) {
|
||||
msg(TL.COMMAND_JOIN_NEGATIVEPOWER, fplayer.describeTo(fme, true));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(faction.getOpen() || faction.isInvited(fplayer) || fme.isAdminBypassing() || Permission.JOIN_ANY.has(sender, false))) {
|
||||
msg(TL.COMMAND_JOIN_REQUIRESINVITATION);
|
||||
if (samePlayer) {
|
||||
faction.msg(TL.COMMAND_JOIN_ATTEMPTEDJOIN, fplayer.describeTo(faction, true));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay
|
||||
if (samePlayer && !canAffordCommand(Conf.econCostJoin, TL.COMMAND_JOIN_TOJOIN.toString())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// trigger the join event (cancellable)
|
||||
FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.COMMAND);
|
||||
Bukkit.getServer().getPluginManager().callEvent(joinEvent);
|
||||
if (joinEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// then make 'em pay (if applicable)
|
||||
if (samePlayer && !payForCommand(Conf.econCostJoin, TL.COMMAND_JOIN_TOJOIN.toString(), TL.COMMAND_JOIN_FORJOIN.toString())) {
|
||||
return;
|
||||
}
|
||||
|
||||
fme.msg(TL.COMMAND_JOIN_SUCCESS, fplayer.describeTo(fme, true), faction.getTag(fme));
|
||||
|
||||
if (!samePlayer) {
|
||||
fplayer.msg(TL.COMMAND_JOIN_MOVED, fme.describeTo(fplayer, true), faction.getTag(fplayer));
|
||||
}
|
||||
faction.msg(TL.COMMAND_JOIN_JOINED, fplayer.describeTo(faction, true));
|
||||
|
||||
fplayer.resetFactionData();
|
||||
fplayer.setFaction(faction);
|
||||
faction.deinvite(fplayer);
|
||||
|
||||
if (Conf.logFactionJoin) {
|
||||
if (samePlayer) {
|
||||
P.p.log(TL.COMMAND_JOIN_JOINEDLOG.toString(), fplayer.getName(), faction.getTag());
|
||||
} else {
|
||||
P.p.log(TL.COMMAND_JOIN_MOVEDLOG.toString(), fme.getName(), fplayer.getName(), faction.getTag());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_JOIN_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.Faction;
|
||||
import com.massivecraft.factions.P;
|
||||
import com.massivecraft.factions.event.FPlayerLeaveEvent;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.struct.Role;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import mkremins.fanciful.FancyMessage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public class CmdKick extends FCommand {
|
||||
|
||||
public CmdKick() {
|
||||
super();
|
||||
this.aliases.add("kick");
|
||||
|
||||
this.optionalArgs.put("player name", "player name");
|
||||
//this.optionalArgs.put("", "");
|
||||
|
||||
this.permission = Permission.KICK.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = true;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
FPlayer toKick = this.argIsSet(0) ? this.argAsBestFPlayerMatch(0) : null;
|
||||
if (toKick == null) {
|
||||
FancyMessage msg = new FancyMessage(TL.COMMAND_KICK_CANDIDATES.toString()).color(ChatColor.GOLD);
|
||||
for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) {
|
||||
String s = player.getName();
|
||||
msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s);
|
||||
}
|
||||
if (fme.getRole() == Role.ADMIN) {
|
||||
for (FPlayer player : myFaction.getFPlayersWhereRole(Role.MODERATOR)) {
|
||||
String s = player.getName();
|
||||
msg.then(s + " ").color(ChatColor.GRAY).tooltip(TL.COMMAND_KICK_CLICKTOKICK.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " kick " + s);
|
||||
}
|
||||
}
|
||||
|
||||
sendFancyMessage(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fme == toKick) {
|
||||
msg(TL.COMMAND_KICK_SELF);
|
||||
msg(TL.GENERIC_YOUMAYWANT.toString() + p.cmdBase.cmdLeave.getUseageTemplate(false));
|
||||
return;
|
||||
}
|
||||
|
||||
Faction toKickFaction = toKick.getFaction();
|
||||
|
||||
if (toKickFaction.isWilderness()) {
|
||||
sender.sendMessage(TL.COMMAND_KICK_NONE.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
// players with admin-level "disband" permission can bypass these requirements
|
||||
if (!Permission.KICK_ANY.has(sender)) {
|
||||
if (toKickFaction != myFaction) {
|
||||
msg(TL.COMMAND_KICK_NOTMEMBER, toKick.describeTo(fme, true), myFaction.describeTo(fme));
|
||||
return;
|
||||
}
|
||||
|
||||
if (toKick.getRole().value >= fme.getRole().value) {
|
||||
msg(TL.COMMAND_KICK_INSUFFICIENTRANK);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Conf.canLeaveWithNegativePower && toKick.getPower() < 0) {
|
||||
msg(TL.COMMAND_KICK_NEGATIVEPOWER);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if economy is enabled, they're not on the bypass list, and this command has a cost set, make sure they can pay
|
||||
if (!canAffordCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// trigger the leave event (cancellable) [reason:kicked]
|
||||
FPlayerLeaveEvent event = new FPlayerLeaveEvent(toKick, toKick.getFaction(), FPlayerLeaveEvent.PlayerLeaveReason.KICKED);
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// then make 'em pay (if applicable)
|
||||
if (!payForCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString(), TL.COMMAND_KICK_FORKICK.toString())) {
|
||||
return;
|
||||
}
|
||||
|
||||
toKickFaction.msg(TL.COMMAND_KICK_FACTION, fme.describeTo(toKickFaction, true), toKick.describeTo(toKickFaction, true));
|
||||
toKick.msg(TL.COMMAND_KICK_KICKED, fme.describeTo(toKick, true), toKickFaction.describeTo(toKick));
|
||||
if (toKickFaction != myFaction) {
|
||||
fme.msg(TL.COMMAND_KICK_KICKS, toKick.describeTo(fme), toKickFaction.describeTo(fme));
|
||||
}
|
||||
|
||||
if (Conf.logFactionKick) {
|
||||
//TODO:TL
|
||||
P.p.log((senderIsConsole ? "A console command" : fme.getName()) + " kicked " + toKick.getName() + " from the cartel: " + toKickFaction.getTag());
|
||||
}
|
||||
|
||||
if (toKick.getRole() == Role.ADMIN) {
|
||||
toKickFaction.promoteNewLeader();
|
||||
}
|
||||
|
||||
toKickFaction.deinvite(toKick);
|
||||
toKick.resetFactionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_KICK_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdLeave extends FCommand {
|
||||
|
||||
public CmdLeave() {
|
||||
super();
|
||||
this.aliases.add("leave");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
//this.optionalArgs.put("", "");
|
||||
|
||||
this.permission = Permission.LEAVE.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = true;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
fme.leave(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.LEAVE_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.Faction;
|
||||
import com.massivecraft.factions.Factions;
|
||||
import com.massivecraft.factions.P;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import com.massivecraft.factions.zcore.util.TagUtil;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class CmdList extends FCommand {
|
||||
|
||||
private String[] defaults = new String[3];
|
||||
|
||||
public CmdList() {
|
||||
super();
|
||||
this.aliases.add("list");
|
||||
this.aliases.add("ls");
|
||||
|
||||
// default values in case user has old config
|
||||
defaults[0] = "&e&m----------&r&e[ &2Cartel List &9{pagenumber}&e/&9{pagecount} &e]&m----------";
|
||||
defaults[1] = "<i>Cartelless<i> {factionless} online";
|
||||
defaults[2] = "<a>{faction} <i>{online} / {members} online, <a>Land / Power / Maxpower: <i>{chunks}/{power}/{maxPower}";
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("page", "1");
|
||||
|
||||
this.permission = Permission.LIST.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = false;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
// if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay
|
||||
if (!payForCommand(Conf.econCostList, "to list the cartels", "for listing the cartels")) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<Faction> factionList = Factions.getInstance().getAllFactions();
|
||||
factionList.remove(Factions.getInstance().getNone());
|
||||
factionList.remove(Factions.getInstance().getSafeZone());
|
||||
factionList.remove(Factions.getInstance().getWarZone());
|
||||
|
||||
// remove exempt factions
|
||||
if (!fme.getPlayer().hasPermission("factions.show.bypassexempt")) {
|
||||
List<String> exemptFactions = P.p.getConfig().getStringList("show-exempt");
|
||||
Iterator<Faction> factionIterator = factionList.iterator();
|
||||
while (factionIterator.hasNext()) {
|
||||
Faction next = factionIterator.next();
|
||||
if (exemptFactions.contains(next.getTag())) {
|
||||
factionIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by total followers first
|
||||
Collections.sort(factionList, new Comparator<Faction>() {
|
||||
@Override
|
||||
public int compare(Faction f1, Faction f2) {
|
||||
int f1Size = f1.getFPlayers().size();
|
||||
int f2Size = f2.getFPlayers().size();
|
||||
if (f1Size < f2Size) {
|
||||
return 1;
|
||||
} else if (f1Size > f2Size) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
// Then sort by how many members are online now
|
||||
Collections.sort(factionList, new Comparator<Faction>() {
|
||||
@Override
|
||||
public int compare(Faction f1, Faction f2) {
|
||||
int f1Size = f1.getFPlayersWhereOnline(true).size();
|
||||
int f2Size = f2.getFPlayersWhereOnline(true).size();
|
||||
if (f1Size < f2Size) {
|
||||
return 1;
|
||||
} else if (f1Size > f2Size) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
ArrayList<String> lines = new ArrayList<String>();
|
||||
|
||||
factionList.add(0, Factions.getInstance().getNone());
|
||||
|
||||
final int pageheight = 9;
|
||||
int pagenumber = this.argAsInt(0, 1);
|
||||
int pagecount = (factionList.size() / pageheight) + 1;
|
||||
if (pagenumber > pagecount) {
|
||||
pagenumber = pagecount;
|
||||
} else if (pagenumber < 1) {
|
||||
pagenumber = 1;
|
||||
}
|
||||
int start = (pagenumber - 1) * pageheight;
|
||||
int end = start + pageheight;
|
||||
if (end > factionList.size()) {
|
||||
end = factionList.size();
|
||||
}
|
||||
|
||||
|
||||
String header = p.getConfig().getString("list.header", defaults[0]);
|
||||
header = header.replace("{pagenumber}", String.valueOf(pagenumber)).replace("{pagecount}", String.valueOf(pagecount));
|
||||
lines.add(p.txt.parse(header));
|
||||
|
||||
for (Faction faction : factionList.subList(start, end)) {
|
||||
if (faction.isWilderness()) {
|
||||
lines.add(p.txt.parse(TagUtil.parsePlain(faction, p.getConfig().getString("list.factionless", defaults[1]))));
|
||||
continue;
|
||||
}
|
||||
lines.add(p.txt.parse(TagUtil.parsePlain(faction, fme, p.getConfig().getString("list.entry", defaults[2]))));
|
||||
}
|
||||
sendMessage(lines);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_LIST_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdLock extends FCommand {
|
||||
|
||||
// TODO: This solution needs refactoring.
|
||||
/*
|
||||
factions.lock:
|
||||
description: use the /f lock [on/off] command to temporarily lock the data files from being overwritten
|
||||
default: op
|
||||
*/
|
||||
|
||||
public CmdLock() {
|
||||
super();
|
||||
this.aliases.add("lock");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("on/off", "flip");
|
||||
|
||||
this.permission = Permission.LOCK.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = false;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
p.setLocked(this.argAsBool(0, !p.getLocked()));
|
||||
msg(p.getLocked() ? TL.COMMAND_LOCK_LOCKED : TL.COMMAND_LOCK_UNLOCKED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_LOCK_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdLogins extends FCommand {
|
||||
|
||||
public CmdLogins() {
|
||||
super();
|
||||
this.aliases.add("login");
|
||||
this.aliases.add("logins");
|
||||
this.aliases.add("logout");
|
||||
this.aliases.add("logouts");
|
||||
this.senderMustBePlayer = true;
|
||||
this.senderMustBeMember = true;
|
||||
this.permission = Permission.MONITOR_LOGINS.node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
boolean monitor = fme.isMonitoringJoins();
|
||||
fme.msg(TL.COMMAND_LOGINS_TOGGLE, String.valueOf(!monitor));
|
||||
fme.setMonitorJoins(!monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_LOGINS_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Board;
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.FLocation;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
|
||||
public class CmdMap extends FCommand {
|
||||
|
||||
public CmdMap() {
|
||||
super();
|
||||
this.aliases.add("map");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("on/off", "once");
|
||||
|
||||
this.permission = Permission.MAP.node;
|
||||
this.disableOnLock = false;
|
||||
|
||||
senderMustBePlayer = true;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
if (this.argIsSet(0)) {
|
||||
if (this.argAsBool(0, !fme.isMapAutoUpdating())) {
|
||||
// Turn on
|
||||
|
||||
// if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay
|
||||
if (!payForCommand(Conf.econCostMap, "to show the map", "for showing the map")) {
|
||||
return;
|
||||
}
|
||||
|
||||
fme.setMapAutoUpdating(true);
|
||||
msg(TL.COMMAND_MAP_UPDATE_ENABLED);
|
||||
|
||||
// And show the map once
|
||||
showMap();
|
||||
} else {
|
||||
// Turn off
|
||||
fme.setMapAutoUpdating(false);
|
||||
msg(TL.COMMAND_MAP_UPDATE_DISABLED);
|
||||
}
|
||||
} else {
|
||||
// if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay
|
||||
if (!payForCommand(Conf.econCostMap, TL.COMMAND_MAP_TOSHOW, TL.COMMAND_MAP_FORSHOW)) {
|
||||
return;
|
||||
}
|
||||
|
||||
showMap();
|
||||
}
|
||||
}
|
||||
|
||||
public void showMap() {
|
||||
sendMessage(Board.getInstance().getMap(myFaction, new FLocation(fme), fme.getPlayer().getLocation().getYaw()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_MAP_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Conf;
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.Faction;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.struct.Role;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import mkremins.fanciful.FancyMessage;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public class CmdMod extends FCommand {
|
||||
|
||||
public CmdMod() {
|
||||
super();
|
||||
this.aliases.add("underboss");
|
||||
this.aliases.add("setunderboss");
|
||||
this.aliases.add("ub");
|
||||
this.aliases.add("setub");
|
||||
this.aliases.add("mod");
|
||||
this.aliases.add("setmod");
|
||||
this.aliases.add("officer");
|
||||
this.aliases.add("setofficer");
|
||||
|
||||
this.optionalArgs.put("player name", "name");
|
||||
//this.optionalArgs.put("", "");
|
||||
|
||||
this.permission = Permission.MOD.node;
|
||||
this.disableOnLock = true;
|
||||
|
||||
senderMustBePlayer = false;
|
||||
senderMustBeMember = true;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
FPlayer you = this.argAsBestFPlayerMatch(0);
|
||||
if (you == null) {
|
||||
FancyMessage msg = new FancyMessage(TL.COMMAND_MOD_CANDIDATES.toString()).color(ChatColor.GOLD);
|
||||
for (FPlayer player : myFaction.getFPlayersWhereRole(Role.NORMAL)) {
|
||||
String s = player.getName();
|
||||
msg.then(s + " ").color(ChatColor.WHITE).tooltip(TL.COMMAND_MOD_CLICKTOPROMOTE.toString() + s).command("/" + Conf.baseCommandAliases.get(0) + " underboss " + s);
|
||||
}
|
||||
|
||||
sendFancyMessage(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean permAny = Permission.MOD_ANY.has(sender, false);
|
||||
Faction targetFaction = you.getFaction();
|
||||
|
||||
if (targetFaction != myFaction && !permAny) {
|
||||
msg(TL.COMMAND_MOD_NOTMEMBER, you.describeTo(fme, true));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fme != null && fme.getRole() != Role.ADMIN && !permAny) {
|
||||
msg(TL.COMMAND_MOD_NOTADMIN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (you == fme && !permAny) {
|
||||
msg(TL.COMMAND_MOD_SELF);
|
||||
return;
|
||||
}
|
||||
|
||||
if (you.getRole() == Role.ADMIN) {
|
||||
msg(TL.COMMAND_MOD_TARGETISADMIN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (you.getRole() == Role.MODERATOR) {
|
||||
// Revoke
|
||||
you.setRole(Role.NORMAL);
|
||||
targetFaction.msg(TL.COMMAND_MOD_REVOKED, you.describeTo(targetFaction, true));
|
||||
msg(TL.COMMAND_MOD_REVOKES, you.describeTo(fme, true));
|
||||
} else {
|
||||
// Give
|
||||
you.setRole(Role.MODERATOR);
|
||||
targetFaction.msg(TL.COMMAND_MOD_PROMOTED, you.describeTo(targetFaction, true));
|
||||
msg(TL.COMMAND_MOD_PROMOTES, you.describeTo(fme, true));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_MOD_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.FPlayer;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdModifyPower extends FCommand {
|
||||
|
||||
public CmdModifyPower() {
|
||||
super();
|
||||
|
||||
this.aliases.add("pm");
|
||||
this.aliases.add("mp");
|
||||
this.aliases.add("modifypower");
|
||||
this.aliases.add("modpower");
|
||||
|
||||
this.requiredArgs.add("name");
|
||||
this.requiredArgs.add("power");
|
||||
|
||||
this.permission = Permission.MODIFY_POWER.node; // admin only perm.
|
||||
|
||||
// Let's not require anything and let console modify this as well.
|
||||
this.senderMustBeAdmin = false;
|
||||
this.senderMustBePlayer = false;
|
||||
this.senderMustBeMember = false;
|
||||
this.senderMustBeModerator = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
// /f modify <name> #
|
||||
FPlayer player = argAsBestFPlayerMatch(0);
|
||||
Double number = argAsDouble(1); // returns null if not a Double.
|
||||
|
||||
if (player == null || number == null) {
|
||||
sender.sendMessage(getHelpShort());
|
||||
return;
|
||||
}
|
||||
|
||||
player.alterPower(number);
|
||||
int newPower = player.getPowerRounded(); // int so we don't have super long doubles.
|
||||
msg(TL.COMMAND_MODIFYPOWER_ADDED, number, player.getName(), newPower);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_MODIFYPOWER_DESCRIPTION;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.P;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
|
||||
public class CmdMoney extends FCommand {
|
||||
|
||||
public CmdMoneyBalance cmdMoneyBalance = new CmdMoneyBalance();
|
||||
public CmdMoneyDeposit cmdMoneyDeposit = new CmdMoneyDeposit();
|
||||
public CmdMoneyWithdraw cmdMoneyWithdraw = new CmdMoneyWithdraw();
|
||||
public CmdMoneyTransferFf cmdMoneyTransferFf = new CmdMoneyTransferFf();
|
||||
public CmdMoneyTransferFp cmdMoneyTransferFp = new CmdMoneyTransferFp();
|
||||
public CmdMoneyTransferPf cmdMoneyTransferPf = new CmdMoneyTransferPf();
|
||||
|
||||
public CmdMoney() {
|
||||
super();
|
||||
this.aliases.add("money");
|
||||
this.aliases.add("stash");
|
||||
this.aliases.add("bal");
|
||||
this.aliases.add("balance");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
//this.optionalArgs.put("","")
|
||||
|
||||
this.isMoneyCommand = true;
|
||||
|
||||
senderMustBePlayer = false;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
|
||||
this.helpLong.add(p.txt.parseTags(TL.COMMAND_MONEY_LONG.toString()));
|
||||
|
||||
this.addSubCommand(this.cmdMoneyBalance);
|
||||
this.addSubCommand(this.cmdMoneyDeposit);
|
||||
this.addSubCommand(this.cmdMoneyWithdraw);
|
||||
// this.addSubCommand(this.cmdMoneyTransferFf);
|
||||
// this.addSubCommand(this.cmdMoneyTransferFp);
|
||||
// this.addSubCommand(this.cmdMoneyTransferPf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
this.commandChain.add(this);
|
||||
P.p.cmdAutoHelp.execute(this.sender, this.args, this.commandChain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_MONEY_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.massivecraft.factions.cmd;
|
||||
|
||||
import com.massivecraft.factions.Faction;
|
||||
import com.massivecraft.factions.integration.Econ;
|
||||
import com.massivecraft.factions.struct.Permission;
|
||||
import com.massivecraft.factions.util.MiscUtil;
|
||||
import com.massivecraft.factions.zcore.util.TL;
|
||||
import net.grandtheftmc.core.util.C;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Locale;
|
||||
|
||||
public class CmdMoneyBalance extends FCommand {
|
||||
|
||||
private final Locale locale = Locale.US;
|
||||
private final NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(locale);
|
||||
|
||||
public CmdMoneyBalance() {
|
||||
super();
|
||||
this.aliases.add("b");
|
||||
this.aliases.add("bal");
|
||||
this.aliases.add("balance");
|
||||
|
||||
//this.requiredArgs.add("");
|
||||
this.optionalArgs.put("cartel", "yours");
|
||||
|
||||
this.permission = Permission.MONEY_BALANCE.node;
|
||||
this.setHelpShort(TL.COMMAND_MONEYBALANCE_SHORT.toString());
|
||||
|
||||
senderMustBePlayer = false;
|
||||
senderMustBeMember = false;
|
||||
senderMustBeModerator = false;
|
||||
senderMustBeAdmin = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() {
|
||||
Faction faction = myFaction;
|
||||
if (this.argIsSet(0)) {
|
||||
faction = this.argAsFaction(0);
|
||||
}
|
||||
|
||||
if (faction == null || !myFaction.isNormal()) return;
|
||||
if (faction != myFaction && !Permission.MONEY_BALANCE_ANY.has(sender, true)) return;
|
||||
|
||||
// Econ.sendBalanceInfo(fme, faction);
|
||||
msg(C.GREEN + "<a>%s's<i> balance is <h>%s<i>.", faction.describeTo(fme, true), currencyFormatter.format(faction.getStash()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TL getUsageTranslation() {
|
||||
return TL.COMMAND_MONEYBALANCE_DESCRIPTION;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue