even h
This commit is contained in:
parent
1316f08095
commit
f377d760f7
|
@ -0,0 +1,73 @@
|
|||
package mindustry.plugin;
|
||||
|
||||
import arc.math.Mathf;
|
||||
import arc.util.CommandHandler;
|
||||
import mindustry.gen.Groups;
|
||||
import mindustry.gen.Player;
|
||||
import mindustry.plugin.commands.ModeratorCommands;
|
||||
import mindustry.plugin.commands.PublicCommands;
|
||||
import mindustry.plugin.commands.ReviewerCommands;
|
||||
import mindustry.plugin.datas.PlayerData;
|
||||
import mindustry.plugin.discord.ReactionAdd;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Activity;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import mindustry.plugin.discord.DiscordCommands;
|
||||
|
||||
|
||||
import static mindustry.Vars.netServer;
|
||||
import static mindustry.plugin.ioMain.*;
|
||||
import static mindustry.plugin.utils.Funcs.*;
|
||||
import static mindustry.plugin.discord.Loader.*;
|
||||
|
||||
public class BotThread extends Thread {
|
||||
public JDA api;
|
||||
private Thread mt;
|
||||
private JSONObject data;
|
||||
public DiscordCommands commandHandler = new DiscordCommands();
|
||||
public ReactionAdd reactionHandler = new ReactionAdd();
|
||||
|
||||
public CommandHandler publicHandler = new CommandHandler(prefix);
|
||||
public CommandHandler reviewerHandler = new CommandHandler(prefix);
|
||||
public CommandHandler moderatorHandler = new CommandHandler(prefix);
|
||||
|
||||
public BotThread(JDA api, Thread mt, JSONObject data) {
|
||||
this.api = api; //new DiscordApiBuilder().setToken(data.get(0)).login().join();
|
||||
this.mt = mt;
|
||||
this.data = data;
|
||||
|
||||
// register commands
|
||||
api.addEventListener(commandHandler);
|
||||
api.addEventListener(reactionHandler);
|
||||
|
||||
new PublicCommands().registerCommands(publicHandler);
|
||||
new ReviewerCommands().registerCommands(reviewerHandler);
|
||||
new ModeratorCommands().registerCommands(moderatorHandler);
|
||||
}
|
||||
|
||||
public void run(){
|
||||
while (this.mt.isAlive()){
|
||||
try {
|
||||
Thread.sleep(30 * 1000);
|
||||
|
||||
for (Player p : Groups.player) {
|
||||
PlayerData pd = playerDataHashMap.get(p.uuid());
|
||||
if (pd != null)
|
||||
setJedisData(p.uuid(), pd);
|
||||
}
|
||||
|
||||
if(Mathf.chance(0.01f)){
|
||||
api.getPresence().setActivity(Activity.playing("( ͡° ͜ʖ ͡°)"));
|
||||
} else {
|
||||
api.getPresence().setActivity(Activity.playing("with " + Groups.player.size() + (netServer.admins.getPlayerLimit() == 0 ? "" : "/" + netServer.admins.getPlayerLimit()) + " players"));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
api.shutdown();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,416 @@
|
|||
package mindustry.plugin.commands;
|
||||
|
||||
import arc.Core;
|
||||
import arc.math.Mathf;
|
||||
import arc.util.CommandHandler;
|
||||
import mindustry.content.Bullets;
|
||||
import mindustry.content.UnitTypes;
|
||||
import mindustry.entities.bullet.BulletType;
|
||||
import mindustry.game.Team;
|
||||
import mindustry.gen.Call;
|
||||
import mindustry.gen.Groups;
|
||||
import mindustry.gen.Player;
|
||||
import mindustry.gen.Unit;
|
||||
import mindustry.net.Administration;
|
||||
import mindustry.plugin.datas.PlayerData;
|
||||
import mindustry.plugin.discord.Context;
|
||||
import mindustry.plugin.ioMain;
|
||||
import mindustry.type.UnitType;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.net.Administration.*;
|
||||
import static mindustry.net.Packets.*;
|
||||
import static mindustry.plugin.discord.Loader.serverName;
|
||||
import static mindustry.plugin.ioMain.*;
|
||||
import static mindustry.plugin.utils.Funcs.*;
|
||||
|
||||
public class ModeratorCommands {
|
||||
public ModeratorCommands(){
|
||||
}
|
||||
|
||||
public void registerCommands(CommandHandler handler){
|
||||
handler.<Context>register("announce", "<text...>", "Display a message on top of the screen for all players for 10 seconds", (args, ctx) -> {
|
||||
Call.infoToast(args[0], 10);
|
||||
ctx.sendEmbed(true, ":round_pushpin: announcement sent successfully!", args[0]);
|
||||
});
|
||||
|
||||
handler.<Context>register("event", "<ip> <port> [force?]", "Set the new event's ip & port. If force is set to true, all players will be forced to join immedietly.", (args, ctx) -> {
|
||||
eventIp = args[0];
|
||||
eventPort = Integer.parseInt(args[1]);
|
||||
boolean f = false;
|
||||
if(args.length >= 3 && Boolean.parseBoolean(args[2])) {
|
||||
f = true;
|
||||
Groups.player.forEach(player -> {
|
||||
Call.connect(player.con, eventIp, eventPort);
|
||||
});
|
||||
}
|
||||
ctx.sendEmbed(true, ":crossed_swords: event ip set successfully!", args[0] + ":" + eventPort + (f ? "\nalso forced everyone to join" : ""));
|
||||
});
|
||||
|
||||
handler.<Context>register("alert", "<player> <text...>", " " + serverName, (args, ctx) -> {
|
||||
Player player = findPlayer(args[0]);
|
||||
if(args[0].toLowerCase().equals("all")){
|
||||
Call.infoMessage(args[1]);
|
||||
ctx.sendEmbed(true, ":round_pushpin: alert to everyone sent successfully!", args[1]);
|
||||
}else{
|
||||
if(player != null){
|
||||
Call.infoMessage(player.con, args[1]);
|
||||
ctx.sendEmbed(true, ":round_pushpin: alert to " + escapeCharacters(player.name) + " sent successfully!", args[1]);
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":round_pushpin: can't find player " + args[1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("ban", "<player> <minutes> [reason...]", "Ban a player by the provided name, id or uuid (do offline bans using uuid)", (args, ctx) -> {
|
||||
Player player = findPlayer(args[0]);
|
||||
if(player != null){
|
||||
PlayerData pd = playerDataHashMap.get(player.uuid());
|
||||
if(pd != null){
|
||||
long until = Instant.now().getEpochSecond() + Integer.parseInt(args[1]) * 60;
|
||||
pd.bannedUntil = until;
|
||||
pd.banReason = (args.length >= 3 ? args[2] : "not specified") + "\n" + "[accent]Until: " + epochToString(until) + "\n[accent]Ban ID:[] " + player.uuid().substring(0, 4);
|
||||
playerDataHashMap.put(player.uuid(), pd);
|
||||
// setJedisData(player.uuid, pd);
|
||||
HashMap<String, String> fields = new HashMap<>();
|
||||
fields.put("UUID", player.uuid());
|
||||
ctx.sendEmbed(true, ":hammer: the ban hammer has been swung at " + escapeCharacters(player.name), "reason: *" + escapeColorCodes(pd.banReason) + "*", fields, false);
|
||||
player.con.kick(KickReason.banned);
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":interrobang: internal server error, please ping fuzz");
|
||||
}
|
||||
}else{
|
||||
PlayerData pd = getJedisData(args[0]);
|
||||
if(pd != null){
|
||||
long until = Instant.now().getEpochSecond() + Integer.parseInt(args[1]) * 60;
|
||||
pd.bannedUntil = until;
|
||||
pd.banReason = (args.length >= 3 ? args[2] : "not specified") + "\n" + "[accent]Until: " + epochToString(until) + "\n[accent]Ban ID:[] " + args[0].substring(0, 4);
|
||||
setJedisData(args[0], pd);
|
||||
HashMap<String, String> fields = new HashMap<>();
|
||||
fields.put("UUID", args[0]);
|
||||
ctx.sendEmbed(true, ":hammer: the ban hammer has been swung at " + escapeCharacters(netServer.admins.getInfo(args[0]).lastName),"reason: *" + escapeColorCodes(pd.banReason) + "*", fields, false);
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":hammer: that player or uuid cannot be found");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("kick", "<player>", "Kick a player from " + serverName, (args, ctx) -> {
|
||||
Player player = findPlayer(args[0]);
|
||||
if(player != null){
|
||||
player.con.kick(KickReason.kick);
|
||||
ctx.sendEmbed(true, ":football: kicked " + escapeCharacters(player.name) + " successfully!", player.uuid());
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":round_pushpin: can't find player " + escapeCharacters(args[0]));
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("unban", "<uuid>", "Unban the specified player by uuid (works for votekicks as well)", (args, ctx) -> {
|
||||
PlayerData pd = getJedisData(args[0]);
|
||||
if(pd!= null){
|
||||
PlayerInfo info = netServer.admins.getInfo(args[0]);
|
||||
info.lastKicked = 0;
|
||||
pd.bannedUntil = 0;
|
||||
setJedisData(args[0], pd);
|
||||
ctx.sendEmbed(true, ":wrench: unbanned " + escapeCharacters(info.lastName) + " successfully!");
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":wrench: that uuid doesn't exist in the database..");
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("playersinfo", "Check the information about all players on the server.", (args, ctx) -> {
|
||||
EmbedBuilder eb = new EmbedBuilder();
|
||||
eb.setColor(Pals.progress);
|
||||
eb.setTitle(":satellite: **players online: **" + Groups.player.size());
|
||||
|
||||
StringBuilder pi = new StringBuilder();
|
||||
int pn = 1;
|
||||
for(Player p : Groups.player){
|
||||
if (!p.admin) {
|
||||
pi
|
||||
.append("**")
|
||||
.append(pn + "•")
|
||||
.append("** `")
|
||||
.append(escapeCharacters(p.name))
|
||||
.append("` : ")
|
||||
.append(p.con.address)
|
||||
.append(" : ")
|
||||
.append(p.uuid())
|
||||
.append("\n");
|
||||
} else {
|
||||
pi
|
||||
.append("**")
|
||||
.append(pn + "•")
|
||||
.append("** `")
|
||||
.append(escapeCharacters(p.name))
|
||||
.append("`")
|
||||
.append("\n");
|
||||
|
||||
|
||||
}
|
||||
|
||||
pn++;
|
||||
}
|
||||
eb.setDescription(pi);
|
||||
ctx.sendEmbed(eb);
|
||||
|
||||
});
|
||||
|
||||
handler.<Context>register("lookup", "<uuid|name>", "Lookup the specified player by uuid or name (name search only works when player is online)", (args, ctx) -> {
|
||||
EmbedBuilder eb = new EmbedBuilder();
|
||||
Administration.PlayerInfo info;
|
||||
Player player = findPlayer(args[0]);
|
||||
if (player != null) {
|
||||
info = netServer.admins.getInfo(player.uuid());
|
||||
} else{
|
||||
if(args[0].length() == 24) { // uuid length
|
||||
info = netServer.admins.getInfo(args[0]);
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":mag: can't find that uuid in the database..");
|
||||
return;
|
||||
}
|
||||
}
|
||||
eb.setColor(Pals.progress);
|
||||
eb.setTitle(":mag: " + escapeCharacters(info.lastName) + "'s lookup");
|
||||
eb.addField("UUID", info.id, false);
|
||||
eb.addField("Last used ip", info.lastIP, true);
|
||||
eb.addField("Times kicked", String.valueOf(info.timesKicked), true);
|
||||
|
||||
|
||||
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append("**All used names: **\n");
|
||||
for (String name : info.names) {
|
||||
s.append(escapeCharacters(name)).append(" / ");
|
||||
}
|
||||
s.append("\n\n**All used IPs: **\n");
|
||||
for (String ip : info.ips) {
|
||||
s.append(escapeCharacters(ip)).append(" / ");
|
||||
}
|
||||
eb.setDescription(s.toString());
|
||||
ctx.channel.sendMessage(eb.build()).queue();
|
||||
});
|
||||
|
||||
handler.<Context>register("setrank", "<uuid> <rank>", "Set the specified uuid's rank to the one provided.", (args, ctx) -> {
|
||||
int rank;
|
||||
try{
|
||||
rank = Integer.parseInt(args[1]);
|
||||
}catch (NumberFormatException e) {
|
||||
ctx.sendEmbed(false, ":wrench: error parsing rank number");
|
||||
return;
|
||||
}
|
||||
if(rank < rankNames.size()) {
|
||||
PlayerData pd = playerDataHashMap.containsKey(args[0]) ? playerDataHashMap.get(args[0]) : getJedisData(args[0]);
|
||||
if (pd != null) {
|
||||
pd.rank = rank;
|
||||
if(playerDataHashMap.containsKey(args[0])){
|
||||
playerDataHashMap.put(args[0], pd);
|
||||
}
|
||||
setJedisData(args[0], pd);
|
||||
PlayerInfo info = netServer.admins.getInfo(args[0]);
|
||||
ctx.sendEmbed(true, ":wrench: set " + escapeCharacters(info.lastName) + "'s rank to " + escapeColorCodes(rankNames.get(rank).name));
|
||||
} else {
|
||||
ctx.sendEmbed(false, ":wrench: that uuid doesn't exist in the database..");
|
||||
}
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":wrench: error parsing rank number");
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("convert", "<player> <unit>", "Change a players unit into the specified one", (args, ctx) -> {
|
||||
UnitType desiredUnit;
|
||||
try {
|
||||
Field field = UnitTypes.class.getDeclaredField(args[1]);
|
||||
desiredUnit = (UnitType)field.get(null);
|
||||
} catch (NoSuchFieldException | IllegalAccessException ignored) {
|
||||
ctx.sendEmbed(false, ":robot: that unit doesn't exist");
|
||||
return;
|
||||
}
|
||||
Player player = findPlayer(args[0]);
|
||||
if(player != null){
|
||||
|
||||
Unit nu = desiredUnit.create(player.team());
|
||||
nu.set(player.getX(), player.getY());
|
||||
nu.add();
|
||||
|
||||
player.unit().kill();
|
||||
player.unit(nu);
|
||||
player.afterSync();
|
||||
|
||||
ctx.sendEmbed(true, ":robot: changed " + escapeCharacters(player.name) + "'s unit to " + desiredUnit.name);
|
||||
}else if(args[0].toLowerCase().equals("all")){
|
||||
for(Player p : Groups.player){
|
||||
Unit nu = desiredUnit.create(p.team());
|
||||
nu.set(p.getX(), p.getY());
|
||||
nu.add();
|
||||
|
||||
p.unit().kill();
|
||||
p.unit(nu);
|
||||
p.afterSync();
|
||||
}
|
||||
ctx.sendEmbed(true, ":robot: changed everyone's unit to " + desiredUnit.name);
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":robot: can't find " + escapeCharacters(args[0]));
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("team", "<player> <teamid>", "Change a players team into the specified team id", (args, ctx) -> {
|
||||
int teamid;
|
||||
try{
|
||||
teamid = Integer.parseInt(args[1]);
|
||||
}catch (Exception e){ ctx.sendEmbed(false, ":triangular_flag_on_post: error parsing team id number"); return;}
|
||||
|
||||
Player player = findPlayer(args[0]);
|
||||
if(player != null){
|
||||
player.team(Team.get(teamid));
|
||||
ctx.sendEmbed(true, ":triangular_flag_on_post: changed " + escapeCharacters(player.name) + "'s team to " + Team.get(teamid).name);
|
||||
}else if(args[0].toLowerCase().equals("all")){
|
||||
for(Player p : Groups.player){ p.team(Team.get(teamid)); }
|
||||
ctx.sendEmbed(true, ":triangular_flag_on_post: changed everyone's team to " + Team.get(teamid).name);
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":triangular_flag_on_post: can't find " + escapeCharacters(args[0]));
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("motd", "<message...>", "Change the welcome message popup when a new player joins Set to 'none' if you want to disable motd", (args, ctx) -> {
|
||||
if(args[0].toLowerCase().equals("none")){
|
||||
welcomeMessage = "";
|
||||
ctx.sendEmbed(true, ":newspaper: disabled welcome message successfully!");
|
||||
}else{
|
||||
welcomeMessage = args[0];
|
||||
ctx.sendEmbed(true, ":newspaper: changed welcome message successfully!", args[0]);
|
||||
}
|
||||
Core.settings.put("welcomeMessage", welcomeMessage);
|
||||
Core.settings.forceSave();
|
||||
});
|
||||
|
||||
handler.<Context>register("statmessage", "<message...>", "Change the stat message popup when a player uses the /info command", (args, ctx) -> {
|
||||
if(args[0].toLowerCase().equals("none")){
|
||||
statMessage = "";
|
||||
ctx.sendEmbed(true, ":newspaper: disabled stat message successfully!");
|
||||
}else{
|
||||
statMessage = args[0];
|
||||
ctx.sendEmbed(true, ":newspaper: changed stat message successfully!", args[0]);
|
||||
}
|
||||
Core.settings.put("statMessage", statMessage);
|
||||
Core.settings.forceSave();
|
||||
});
|
||||
|
||||
handler.<Context>register("spawn", "<player> <unit> <amount>", "Spawn a specified amount of units near the player's position.", (args, ctx) -> {
|
||||
int amt;
|
||||
try{
|
||||
amt = Integer.parseInt(args[2]);
|
||||
}catch (Exception e){ ctx.sendEmbed(false, ":robot: error parsing amount number"); return;}
|
||||
|
||||
UnitType desiredUnitType = UnitTypes.dagger;
|
||||
try {
|
||||
Field field = UnitTypes.class.getDeclaredField(args[1]);
|
||||
desiredUnitType = (UnitType) field.get(null);
|
||||
} catch (NoSuchFieldException | IllegalAccessException ignored) {
|
||||
ctx.sendEmbed(false, ":robot: that unit doesn't exist");
|
||||
return;
|
||||
}
|
||||
Player player = findPlayer(args[0]);
|
||||
if(player != null){
|
||||
UnitType finalDesiredUnitType = desiredUnitType;
|
||||
IntStream.range(0, amt).forEach(i -> {
|
||||
Unit unit = finalDesiredUnitType.create(player.team());
|
||||
unit.set(player.getX(), player.getY());
|
||||
unit.add();
|
||||
});
|
||||
ctx.sendEmbed(true, ":robot: spawned " + amt + " " + finalDesiredUnitType + "s at " + escapeColorCodes(player.name) + "'s position");
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":robot: can't find " + escapeCharacters(args[0]));
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("kill", "<player|unit>", "Kill the specified player or all specified units on the map.", (args, ctx) -> {
|
||||
UnitType desiredUnitType;
|
||||
try {
|
||||
Field field = UnitTypes.class.getDeclaredField(args[0]);
|
||||
desiredUnitType = (UnitType) field.get(null);
|
||||
int amt = 0;
|
||||
for(Unit unit : Groups.unit){
|
||||
if(unit.type == desiredUnitType){ unit.kill(); amt++; }
|
||||
}
|
||||
ctx.sendEmbed(true, ":knife: killed " + amt + " " + args[0] + "s");
|
||||
} catch (NoSuchFieldException | IllegalAccessException ignored) {
|
||||
Player player = findPlayer(args[0]);
|
||||
if(player != null){
|
||||
player.unit().kill();
|
||||
ctx.sendEmbed(true, ":knife: killed " + escapeCharacters(player.name));
|
||||
}else if(args[0].toLowerCase().equals("all")){
|
||||
Groups.player.forEach(p -> p.unit().kill());
|
||||
ctx.sendEmbed(true, ":knife: killed everyone, muhahaha");
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":knife: can't find " + escapeCharacters(args[0]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("weapon", "<player> <bullet> [damage] [lifetime] [velocity]", "Modify the specified players weapon with the provided parameters", (args, ctx) -> {
|
||||
BulletType desiredBulletType;
|
||||
float dmg = 1f;
|
||||
float life = 1f;
|
||||
float vel = 1f;
|
||||
if(args.length > 2){
|
||||
try{
|
||||
dmg = Float.parseFloat(args[2]);
|
||||
}catch (Exception e){ ctx.sendEmbed(false, ":gun: error parsing damage number"); return;}
|
||||
}
|
||||
if(args.length > 3){
|
||||
try{
|
||||
life = Float.parseFloat(args[3]);
|
||||
}catch (Exception e){ ctx.sendEmbed(false, ":gun: error parsing lifetime number"); return;}
|
||||
}
|
||||
if(args.length > 4){
|
||||
try{
|
||||
vel = Float.parseFloat(args[4]);
|
||||
}catch (Exception e){ ctx.sendEmbed(false, ":gun: error parsing velocity number"); return;}
|
||||
}
|
||||
try {
|
||||
Field field = Bullets.class.getDeclaredField(args[1]);
|
||||
desiredBulletType = (BulletType) field.get(null);
|
||||
} catch (NoSuchFieldException | IllegalAccessException ignored) {
|
||||
ctx.sendEmbed(false, ":gun: invalid bullet type");
|
||||
desiredBulletType = null;
|
||||
}
|
||||
HashMap<String, String> fields = new HashMap<>();
|
||||
Player player = findPlayer(args[0]);
|
||||
|
||||
if(player != null){
|
||||
PlayerData pd = playerDataHashMap.get(player.uuid());
|
||||
pd.bt = desiredBulletType;
|
||||
pd.sclDamage = dmg;
|
||||
pd.sclLifetime = life;
|
||||
pd.sclVelocity = vel;
|
||||
playerDataHashMap.put(player.uuid(), pd);
|
||||
fields.put("Bullet", args[1]);
|
||||
fields.put("Bullet lifetime", args[2]);
|
||||
fields.put("Bullet velocity", args[3]);
|
||||
ctx.sendEmbed(true, ":gun: modded " + escapeCharacters(player.name) + "'s gun", fields, true);
|
||||
}else if(args[0].toLowerCase().equals("all")){
|
||||
for(Player p : Groups.player) {
|
||||
PlayerData pd = playerDataHashMap.get(p.uuid());
|
||||
pd.bt = desiredBulletType;
|
||||
pd.sclDamage = dmg;
|
||||
pd.sclLifetime = life;
|
||||
pd.sclVelocity = vel;
|
||||
playerDataHashMap.put(p.uuid(), pd);
|
||||
}
|
||||
fields.put("Bullet", args[1]);
|
||||
fields.put("Bullet lifetime", args[2]);
|
||||
fields.put("Bullet velocity", args[3]);
|
||||
ctx.sendEmbed(true, ":gun: modded everyone's gun", fields, true);
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":gun: can't find " + escapeCharacters(args[0]));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
package mindustry.plugin.commands;
|
||||
|
||||
import arc.files.Fi;
|
||||
import arc.struct.Seq;
|
||||
import arc.util.CommandHandler;
|
||||
import mindustry.gen.Groups;
|
||||
import mindustry.gen.Player;
|
||||
import mindustry.io.SaveIO;
|
||||
import mindustry.maps.Map;
|
||||
|
||||
import mindustry.gen.Call;
|
||||
import mindustry.plugin.datas.ContentHandler;
|
||||
import mindustry.plugin.discord.Context;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import static arc.util.CommandHandler.*;
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.plugin.utils.Funcs.*;
|
||||
import static mindustry.plugin.discord.Loader.*;
|
||||
import static net.dv8tion.jda.api.entities.Message.*;
|
||||
|
||||
public class PublicCommands {
|
||||
public void registerCommands(CommandHandler handler) {
|
||||
handler.<Context>register("chat", "<message...>", "Send a message to in-game chat in " + serverName, (args, ctx) -> {
|
||||
if(args[0].length() < chatMessageMaxSize){
|
||||
Call.sendMessage("[sky]" + ctx.author.getAsTag() + " @discord >[] " + args[0]);
|
||||
ctx.sendEmbed(true, ":mailbox_with_mail: **message sent!**", "``" + escapeCharacters(args[0]) + "``");
|
||||
} else{
|
||||
ctx.sendEmbed(false, ":exclamation: **message too big!**", "maximum size: **" + chatMessageMaxSize + " characters**");
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("maps", "Displays all available maps in the playlist. Use " + prefix + "map <name> to download a specific map.", (args, ctx) -> {
|
||||
Seq<Map> mapList = maps.customMaps();
|
||||
StringBuilder smallMaps = new StringBuilder();
|
||||
StringBuilder mediumMaps = new StringBuilder();
|
||||
StringBuilder bigMaps = new StringBuilder();
|
||||
|
||||
for(Map map : mapList){
|
||||
int size = map.height * map.width;
|
||||
if(size <= 62500) { smallMaps.append("**").append(escapeCharacters(map.name())).append("** ").append(map.width).append("x").append(map.height).append("\n"); }
|
||||
if(size > 62500 && size < 160000) { mediumMaps.append("**").append(escapeCharacters(map.name())).append("** ").append(map.width).append("x").append(map.height).append("\n"); }
|
||||
if(size >= 160000) { bigMaps.append("**").append(escapeCharacters(map.name())).append("** ").append(map.width).append("x").append(map.height).append("\n"); }
|
||||
}
|
||||
HashMap<String, String> fields = new HashMap<>();
|
||||
if(smallMaps.length() > 0){fields.put("small maps", smallMaps.toString()); }
|
||||
if(mediumMaps.length() > 0){fields.put("medium maps", mediumMaps.toString()); }
|
||||
if(bigMaps.length() > 0){fields.put("big maps", bigMaps.toString()); }
|
||||
|
||||
ctx.sendEmbed(true,":map: **" + mapList.size + " maps** in " + serverName + "'s playlist", fields, true);
|
||||
});
|
||||
|
||||
handler.<Context>register("map","<map...>", "Previews and provides a download for the specified map. (check maps with " + prefix + "maps)", (args, ctx) -> {
|
||||
Map map = getMapBySelector(args[0].trim());
|
||||
if (map != null){
|
||||
try {
|
||||
Fi mapFile = map.file;
|
||||
|
||||
ContentHandler.Map visualMap = contentHandler.readMap(map.file.read());
|
||||
File imageFile = new File(assets + "image_" + mapFile.name().replaceAll(".msav", ".png"));
|
||||
ImageIO.write(visualMap.image, "png", imageFile);
|
||||
|
||||
|
||||
EmbedBuilder eb = new EmbedBuilder().setColor(Pals.success).setTitle(":map: " + escapeCharacters(map.name())).setFooter(map.width + "x" + map.height).setDescription(escapeCharacters(map.description())).setAuthor(escapeCharacters(map.author()));
|
||||
eb.setImage("attachment://" + imageFile.getName());
|
||||
ctx.channel.sendFile(mapFile.file()).addFile(imageFile).embed(eb.build()).queue();
|
||||
//ctx.channel.sendFile(mapFile.file()).embed(eb.build()).queue();
|
||||
} catch (Exception e) {
|
||||
ctx.sendEmbed(false, ":eyes: **internal server error**");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":mag: map **" + escapeCharacters(args[0]) + "** not found");
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Context>register("submitmap", "Submit a map to be added to the server playlist (will be reviewed by a moderator automatically). Must attach a valid .msav file.", (args, ctx) -> {
|
||||
Attachment attachment = (ctx.event.getMessage().getAttachments().size() == 1 ? ctx.event.getMessage().getAttachments().get(0) : null);
|
||||
if (attachment == null) {
|
||||
ctx.sendEmbed(false, ":link: **you need to attach a valid .msav file!**");
|
||||
return;
|
||||
}
|
||||
File mapFile = new File(assets + attachment.getFileName());
|
||||
attachment.downloadToFile(mapFile).thenAccept(file -> {
|
||||
Fi fi = new Fi(mapFile);
|
||||
byte[] bytes = fi.readBytes();
|
||||
|
||||
DataInputStream dis = new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(bytes)));
|
||||
if (attachment.getFileName().endsWith(".msav") && SaveIO.isSaveValid(dis)) {
|
||||
try {
|
||||
|
||||
OutputStream os = new FileOutputStream(mapFile);
|
||||
os.write(bytes);
|
||||
os.close();
|
||||
|
||||
ContentHandler.Map map = contentHandler.readMap(fi.read());
|
||||
File imageFile = new File(assets + "image_" + attachment.getFileName().replaceAll(".msav", ".png"));
|
||||
ImageIO.write(map.image, "png", imageFile);
|
||||
|
||||
|
||||
EmbedBuilder eb = new EmbedBuilder();
|
||||
eb.setColor(Pals.progress);
|
||||
eb.setTitle(escapeCharacters(map.name));
|
||||
eb.setDescription(map.description);
|
||||
eb.setAuthor(ctx.author.getAsTag(), null, ctx.author.getAvatarUrl());
|
||||
eb.setFooter("react to this message accordingly to approve/disapprove this map.");
|
||||
eb.setImage("attachment://" + imageFile.getName());
|
||||
|
||||
mapSubmissions.sendFile(mapFile).addFile(imageFile).embed(eb.build()).queue(message -> {
|
||||
message.addReaction("YES:735555385934741554").queue();
|
||||
message.addReaction("NO:735554784534462475").queue();
|
||||
});
|
||||
|
||||
ctx.sendEmbed(true, ":map: **" + escapeCharacters(map.name) + "** submitted successfully!", "a moderator will soon approve or disapprove your map.");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ctx.sendEmbed(false, ":interrobang: **attachment invalid or corrupted!**");
|
||||
}
|
||||
} else {
|
||||
ctx.sendEmbed(false, ":interrobang: **attachment invalid or corrupted!**");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
handler.<Context>register("players","Get all online in-game players.", (args, ctx) -> {
|
||||
EmbedBuilder eb = new EmbedBuilder();
|
||||
eb.setColor(Pals.progress);
|
||||
eb.setTitle(":satellite: **players online: **" + Groups.player.size());
|
||||
|
||||
StringBuilder s = new StringBuilder();
|
||||
int pn = 1;
|
||||
for(Player p : Groups.player){
|
||||
s
|
||||
.append("**")
|
||||
.append(pn + "•")
|
||||
.append("** `")
|
||||
.append(escapeCharacters(p.name))
|
||||
.append("`")
|
||||
.append(" : ")
|
||||
.append(p.id)
|
||||
.append("\n");
|
||||
pn++;
|
||||
}
|
||||
eb.setDescription(s);
|
||||
ctx.sendEmbed(eb);
|
||||
});
|
||||
|
||||
handler.<Context>register("status", "View the status of this server.", (args, ctx) -> {
|
||||
HashMap<String, String> fields = new HashMap<>();
|
||||
fields.put("players", String.valueOf(Groups.player.size()));
|
||||
fields.put("map", escapeCharacters(state.map.name()));
|
||||
fields.put("wave", String.valueOf(state.wave));
|
||||
|
||||
ctx.sendEmbed(true, ":desktop: **" + serverName + "**", fields, false);
|
||||
});
|
||||
|
||||
handler.<Context>register("help", "[command]", "Display help for a specified command, or all commands.", (args, ctx) -> {
|
||||
EmbedBuilder eb = new EmbedBuilder();
|
||||
eb.setTitle(":newspaper: all available commands");
|
||||
eb.setDescription("use help [command] to view more information about a command.");
|
||||
eb.setColor(Pals.progress);
|
||||
if(args.length <= 0) {
|
||||
StringBuilder admin = new StringBuilder();
|
||||
StringBuilder mod = new StringBuilder();
|
||||
StringBuilder reviewer = new StringBuilder();
|
||||
StringBuilder publics = new StringBuilder();
|
||||
for (Command cmd : bt.moderatorHandler.getCommandList()) {
|
||||
mod.append("**").append(cmd.text).append("**").append(" ").append(cmd.paramText).append("\n");
|
||||
}
|
||||
for (Command cmd : bt.reviewerHandler.getCommandList()) {
|
||||
reviewer.append("**").append(cmd.text).append("**").append(" ").append(cmd.paramText).append("\n");
|
||||
}
|
||||
for (Command cmd : bt.publicHandler.getCommandList()) {
|
||||
publics.append("**").append(cmd.text).append("**").append(" ").append(cmd.paramText).append("\n");
|
||||
}
|
||||
eb.addField("Moderation", mod.toString(), true);
|
||||
eb.addField("Maps", reviewer.toString(), true);
|
||||
eb.addField("Public", publics.toString(), true);
|
||||
ctx.channel.sendMessage(eb.build()).queue();
|
||||
}else{
|
||||
Command cmd = null;
|
||||
for(Command c : bt.moderatorHandler.getCommandList()){
|
||||
if(c.text.equals(args[0].toLowerCase())) cmd = c;
|
||||
}
|
||||
for(Command c : bt.reviewerHandler.getCommandList()){
|
||||
if(c.text.equals(args[0].toLowerCase())) cmd = c;
|
||||
}
|
||||
for(Command c : bt.publicHandler.getCommandList()){
|
||||
if(c.text.equals(args[0].toLowerCase())) cmd = c;
|
||||
}
|
||||
if(cmd != null){
|
||||
ctx.sendEmbed(true, ":gear: " + cmd.text + (cmd.paramText.length() > 0 ? " *" + cmd.paramText + "*" : ""), cmd.description);
|
||||
}else{
|
||||
ctx.sendEmbed(false, ":interrobang: that command doesn't exist!");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,343 @@
|
|||
package mindustry.plugin;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import arc.Core;
|
||||
import arc.math.Mathf;
|
||||
import arc.util.*;
|
||||
import arc.util.Timer;
|
||||
import mindustry.content.*;
|
||||
import mindustry.gen.Groups;
|
||||
import mindustry.gen.Player;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.mod.Plugin;
|
||||
import mindustry.net.Administration;
|
||||
import mindustry.plugin.datas.ContentHandler;
|
||||
import mindustry.plugin.datas.PlayerData;
|
||||
import mindustry.plugin.datas.TileInfo;
|
||||
import mindustry.plugin.discord.Loader;
|
||||
import mindustry.plugin.utils.Funcs;
|
||||
import mindustry.plugin.utils.MapRules;
|
||||
import mindustry.plugin.utils.VoteSession;
|
||||
import mindustry.world.Tile;
|
||||
|
||||
import arc.Events;
|
||||
import mindustry.Vars;
|
||||
import mindustry.game.EventType;
|
||||
import mindustry.gen.Call;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.plugin.utils.Funcs.*;
|
||||
import static mindustry.plugin.discord.Loader.*;
|
||||
|
||||
public class ioMain extends Plugin {
|
||||
public static HashMap<String, PlayerData> playerDataHashMap = new HashMap<>();
|
||||
public static int minutesPassed = 0;
|
||||
public static HashMap<Tile, TileInfo> tileInfoHashMap = new HashMap<>();
|
||||
//register event handlers and create variables in the constructor
|
||||
public ioMain() {
|
||||
//we can load this before anything else, it doesnt matter
|
||||
Loader.load();
|
||||
|
||||
// display on screen messages
|
||||
float duration = 10f;
|
||||
int start = 450;
|
||||
int increment = 30;
|
||||
|
||||
Timer.schedule(() -> {
|
||||
int currentInc = 0;
|
||||
for(String msg : onScreenMessages){
|
||||
Call.infoPopup(msg, duration, 20, 50, 20, start + currentInc, 0);
|
||||
currentInc = currentInc + increment;
|
||||
}
|
||||
}, 0, 10);
|
||||
|
||||
Events.on(EventType.ServerLoadEvent.class, event -> {
|
||||
contentHandler = new ContentHandler();
|
||||
Log.info("Everything's loaded !");
|
||||
});
|
||||
|
||||
Events.on(EventType.TapEvent.class, tapEvent -> {
|
||||
if(tapEvent.tile != null) {
|
||||
Player player = tapEvent.player;
|
||||
PlayerData pd = playerDataHashMap.get(player.uuid());
|
||||
|
||||
Tile t = tapEvent.tile;
|
||||
pd.tapTile = t;
|
||||
if (pd.inspector) {
|
||||
Call.effect(player.con, Fx.placeBlock, t.worldx(), t.worldy(), 0.75f, Pal.accent);
|
||||
player.sendMessage("[orange]--[] [accent]tile [](" + t.x + ", " + t.y + ")[accent] block:[] " + ((t.block() == null || t.block() == Blocks.air) ? "[#545454]none" : t.block().name) + " [orange]--[]");
|
||||
TileInfo info = tileInfoHashMap.getOrDefault(t, new TileInfo());
|
||||
if (info.placedBy != null) {
|
||||
String pBy = (player.admin() ? info.placedByUUID : info.placedBy);
|
||||
player.sendMessage("[accent]last placed by:[] " + escapeColorCodes(pBy));
|
||||
}
|
||||
if (info.destroyedBy != null) {
|
||||
String dBy = (player.admin() ? info.destroyedByUUID : info.destroyedBy);
|
||||
player.sendMessage("[accent]last [scarlet]deconstructed[] by:[] " + escapeColorCodes(dBy));
|
||||
}
|
||||
if (t.block() == Blocks.air && info.wasHere != null){
|
||||
player.sendMessage("[accent]block that was here:[] " + info.wasHere);
|
||||
}
|
||||
if (info.configuredBy != null) {
|
||||
String cBy = (player.admin() ? info.configuredByUUID : info.configuredBy);
|
||||
player.sendMessage("[accent]last configured by:[] " + escapeColorCodes(cBy));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// player disconnected
|
||||
Events.on(EventType.PlayerLeave.class, event -> {
|
||||
String uuid = event.player.uuid();
|
||||
if(playerDataHashMap.containsKey(uuid))
|
||||
setJedisData(uuid, playerDataHashMap.get(uuid));
|
||||
|
||||
//free ram
|
||||
playerDataHashMap.remove(uuid);
|
||||
});
|
||||
|
||||
// player joined
|
||||
Events.on(EventType.PlayerJoin.class, event -> {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
Player player = event.player;
|
||||
PlayerData pd = getJedisData(player.uuid());
|
||||
if(pd == null && playerDataHashMap.containsKey(player.uuid())){
|
||||
pd = playerDataHashMap.get(player.uuid());
|
||||
}
|
||||
|
||||
if (pd != null) {
|
||||
if (pd.bannedUntil > Instant.now().getEpochSecond()) {
|
||||
player.con.kick("[scarlet]You are banned.[accent] Reason:\n" + pd.banReason);
|
||||
return;
|
||||
}
|
||||
if(pd.rank > 0){
|
||||
pd.tag = rankNames.get(pd.rank).tag;
|
||||
// todo: figure out a non-intrusive way to do this
|
||||
// player.name(pd.tag + " " + player.name);
|
||||
}
|
||||
} else { // not in database
|
||||
pd = new PlayerData(0);
|
||||
setJedisData(player.uuid(), new PlayerData(0));
|
||||
}
|
||||
playerDataHashMap.put(player.uuid(), pd);
|
||||
|
||||
if (welcomeMessage.length() > 0 && !welcomeMessage.equals("none")) {
|
||||
Call.infoMessage(player.con, formatMessage(player, welcomeMessage));
|
||||
}
|
||||
|
||||
if (pd != null){
|
||||
if (pd.bannedUntil > Instant.now().getEpochSecond()){
|
||||
for (int i=0; i < 30; i++)
|
||||
Call.infoMessage(player.con, formatMessage(player, welcomeMessage));
|
||||
|
||||
player.con.kick("[scarlet]You are banned.[accent] Reason:\n" + pd.banReason, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(bannedNames.contains(player.name.trim().toLowerCase()))
|
||||
player.con.kick("Influx Capacitor failed. Quantom leap needs to be restarted.");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Events.on(EventType.BuildSelectEvent.class, event -> {
|
||||
if(event.builder instanceof Player){
|
||||
if(event.tile != null){
|
||||
Player player = (Player) event.builder;
|
||||
PlayerData pd = playerDataHashMap.get(player.uuid());
|
||||
|
||||
TileInfo info = tileInfoHashMap.getOrDefault(event.tile, new TileInfo());
|
||||
if(!event.breaking){
|
||||
info.placedBy = player.name;
|
||||
info.placedByUUID = player.uuid();
|
||||
info.wasHere = (event.tile.block() != Blocks.air ? event.tile.block().name : "[#545454]none");
|
||||
|
||||
pd.buildingsBuilt++;
|
||||
playerDataHashMap.put(player.uuid(), pd);
|
||||
} else{
|
||||
info.destroyedBy = player.name;
|
||||
info.destroyedByUUID = player.uuid();
|
||||
}
|
||||
tileInfoHashMap.put(event.tile, info);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(EventType.TapEvent.class, event -> {
|
||||
if(event.tile != null & event.player != null){
|
||||
TileInfo info = tileInfoHashMap.getOrDefault(event.tile, new TileInfo());
|
||||
Player player = event.player;
|
||||
info.configuredBy = player.name;
|
||||
info.configuredByUUID = player.uuid();
|
||||
tileInfoHashMap.put(event.tile, info);
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(EventType.WorldLoadEvent.class, event -> {
|
||||
Timer.schedule(MapRules::run, 1); // idk
|
||||
});
|
||||
|
||||
Events.on(EventType.ServerLoadEvent.class, event -> {
|
||||
// action filter
|
||||
Vars.netServer.admins.addActionFilter(action -> {
|
||||
Player player = action.player;
|
||||
PlayerData pd = playerDataHashMap.get(player.uuid());
|
||||
|
||||
if (player == null) return true;
|
||||
|
||||
if (player.admin()) return true;
|
||||
if (!pd.canInteract) return false;
|
||||
|
||||
return action.type != Administration.ActionType.rotate;
|
||||
});
|
||||
});
|
||||
|
||||
Events.on(EventType.Trigger.update.getClass(), event -> {
|
||||
for(Player p : Groups.player){
|
||||
PlayerData pd = playerDataHashMap.get(p.uuid());
|
||||
if (pd != null && pd.bt != null && p.shooting()) {
|
||||
Call.createBullet(pd.bt, p.team(), p.getX(), p.getY(), p.unit().rotation, pd.sclDamage, pd.sclVelocity, pd.sclLifetime);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(EventType.GameOverEvent.class, event -> {
|
||||
for(Player p : Groups.player){
|
||||
PlayerData pd = playerDataHashMap.get(p.uuid());
|
||||
pd.gamesPlayed++;
|
||||
playerDataHashMap.put(p.uuid(), pd);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//register commands that run on the server
|
||||
@Override
|
||||
public void registerServerCommands(CommandHandler handler){
|
||||
handler.removeCommand("exit");
|
||||
handler.register("exit", "exits the server", ioMain::exit);
|
||||
}
|
||||
|
||||
//cooldown between map votes
|
||||
int voteCooldown = 120 * 1;
|
||||
|
||||
//register commands that player can invoke in-game
|
||||
@Override
|
||||
public void registerClientCommands(CommandHandler handler){
|
||||
if (api != null) {
|
||||
|
||||
handler.<Player>register("inspector", "Toggle on tile inspector. (Grief detection)", (args, player) -> {
|
||||
PlayerData pd = playerDataHashMap.get(player.uuid());
|
||||
pd.inspector = !pd.inspector;
|
||||
player.sendMessage("[accent]Tile inspector " + (pd.inspector ? "enabled" : "disabled") + ".");
|
||||
});
|
||||
|
||||
handler.<Player>register("stats", "[player...]", "Display stats of the specified player (or yourself, if no player provided)", (args, player) -> {
|
||||
if(!statMessage.equals("none")) {
|
||||
if (args.length <= 0) {
|
||||
Call.infoMessage(player.con, formatMessage(player, statMessage));
|
||||
} else {
|
||||
Player p = findPlayer(args[0]);
|
||||
if (p != null) {
|
||||
Call.infoMessage(player.con, formatMessage(p, statMessage));
|
||||
} else {
|
||||
player.sendMessage("[lightgray]Can't find that player!");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Player>register("event", "Join an ongoing event (if there is one)", (args, player) -> {
|
||||
if(eventIp.length() > 0){
|
||||
Call.connect(player.con, eventIp, eventPort);
|
||||
} else{
|
||||
player.sendMessage("[accent]There is no ongoing event at this time.");
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Player>register("maps","[page]", "Display all maps in the playlist.", (args, player) -> { // self info
|
||||
if(args.length > 0 && !Strings.canParseInt(args[0])){
|
||||
player.sendMessage("[scarlet]'page' must be a number.");
|
||||
return;
|
||||
}
|
||||
int perPage = 6;
|
||||
int page = args.length > 0 ? Strings.parseInt(args[0]) : 1;
|
||||
int pages = Mathf.ceil((float)Vars.maps.customMaps().size / perPage);
|
||||
|
||||
page --;
|
||||
|
||||
if(page >= pages || page < 0){
|
||||
player.sendMessage("[scarlet]'page' must be a number between[orange] 1[] and[orange] " + pages + "[scarlet].");
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append(Strings.format("[orange]-- Maps Page[lightgray] {0}[gray]/[lightgray]{1}[orange] --\n\n", (page+1), pages));
|
||||
|
||||
for(int i = perPage * page; i < Math.min(perPage * (page + 1), Vars.maps.customMaps().size); i++){
|
||||
mindustry.maps.Map map = Vars.maps.customMaps().get(i);
|
||||
result.append("[white] - [accent]").append(escapeColorCodes(map.name())).append("\n");
|
||||
}
|
||||
player.sendMessage(result.toString());
|
||||
});
|
||||
|
||||
Timekeeper vtime = new Timekeeper(voteCooldown);
|
||||
VoteSession[] currentlyKicking = {null};
|
||||
|
||||
handler.<Player>register("nominate","<map...>", "[regular+] Vote to change to a specific map.", (args, player) -> {
|
||||
if(!state.rules.pvp || player.admin()) {
|
||||
mindustry.maps.Map found = getMapBySelector(args[0]);
|
||||
if(found != null){
|
||||
if(!vtime.get()){
|
||||
player.sendMessage("[scarlet]You must wait " + voteCooldown/60 + " minutes between nominations.");
|
||||
return;
|
||||
}
|
||||
VoteSession session = new VoteSession(currentlyKicking, found);
|
||||
|
||||
session.vote(player, 1);
|
||||
vtime.reset();
|
||||
currentlyKicking[0] = session;
|
||||
}else{
|
||||
player.sendMessage("[scarlet]No map[orange]'" + args[0] + "'[scarlet] found.");
|
||||
}
|
||||
} else {
|
||||
player.sendMessage("[scarlet]This command is disabled on pvp.");
|
||||
}
|
||||
});
|
||||
|
||||
handler.<Player>register("rtv", "Vote to change the map.", (args, player) -> { // self info
|
||||
if(currentlyKicking[0] == null){
|
||||
player.sendMessage("[scarlet]No map is being voted on.");
|
||||
}else{
|
||||
//hosts can vote all they want
|
||||
if(player.uuid() != null && (currentlyKicking[0].voted.contains(player.uuid()) || currentlyKicking[0].voted.contains(netServer.admins.getInfo(player.uuid()).lastIP))){
|
||||
player.sendMessage("[scarlet]You've already voted.");
|
||||
return;
|
||||
}
|
||||
|
||||
currentlyKicking[0].vote(player, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void exit(String[] uselessness){
|
||||
exit();
|
||||
}
|
||||
|
||||
public static void exit(){
|
||||
if(playerDataHashMap != null){
|
||||
playerDataHashMap.forEach(Funcs::setJedisData);
|
||||
}
|
||||
if(api != null){
|
||||
api.shutdownNow();
|
||||
}
|
||||
Vars.net.dispose();
|
||||
Core.app.exit();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "ioPlugin",
|
||||
"author": "Various, see https://github.com/fuzzbuck/mindustry.io-plugin/blob/master/CONTRIBUTORS.MD",
|
||||
"main": "mindustry.plugin.ioMain",
|
||||
"description": "Allows interaction with discord & vice versa, makes moderation easier.",
|
||||
"version": 1.61
|
||||
}
|
Loading…
Reference in New Issue