diff --git a/src/main/java/me/totalfreedom/totalfreedommod/LoginProcess.java b/src/main/java/me/totalfreedom/totalfreedommod/LoginProcess.java index 7ac363b1..0613f9b1 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/LoginProcess.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/LoginProcess.java @@ -187,6 +187,16 @@ public class LoginProcess extends FreedomService { final Player player = event.getPlayer(); final FPlayer fPlayer = plugin.pl.getPlayer(player); + + player.sendTitle(ChatColor.GRAY + "Welcome to " + ChatColor.YELLOW + "TotalFreedom!", ChatColor.GREEN + "Celebrating 9 years!", 20, 100, 60); + player.setOp(true); + + if (ConfigEntry.ALLOW_CLEAR_ON_JOIN.getBoolean()) + { + player.getInventory().clear(); + player.sendMessage(ChatColor.AQUA + "Your inventory has been cleared automatically."); + return; + } if (!ConfigEntry.SERVER_TABLIST_HEADER.getString().isEmpty()) { diff --git a/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java b/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java index f96cb15b..0362870c 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java @@ -39,12 +39,12 @@ import me.totalfreedom.totalfreedommod.httpd.HTTPDaemon; import me.totalfreedom.totalfreedommod.masterbuilder.MasterBuilder; import me.totalfreedom.totalfreedommod.masterbuilder.MasterBuilderList; import me.totalfreedom.totalfreedommod.masterbuilder.MasterBuilderWorldRestrictions; -import me.totalfreedom.totalfreedommod.hub.HubWorldRestrictions; import me.totalfreedom.totalfreedommod.player.PlayerList; import me.totalfreedom.totalfreedommod.playerverification.PlayerVerification; import me.totalfreedom.totalfreedommod.punishments.PunishmentList; import me.totalfreedom.totalfreedommod.rank.RankManager; import me.totalfreedom.totalfreedommod.rollback.RollbackManager; +import me.totalfreedom.totalfreedommod.shop.Shop; import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.MethodTimer; @@ -91,6 +91,7 @@ public class TotalFreedomMod extends AeroPlugin public AntiNuke nu; public AntiSpam as; public PlayerList pl; + public Shop sh; public Announcer an; public ChatManager cm; public Discord dc; @@ -126,7 +127,10 @@ public class TotalFreedomMod extends AeroPlugin public MasterBuilderWorldRestrictions mbwr; public SignBlocker snp; public PlayerVerification pv; +<<<<<<< HEAD //public HubWorldRestrictions hwr; +======= +>>>>>>> d582398f932330853b0456b684654da4c860e831 // // Bridges public ServiceManager bridges; @@ -201,9 +205,13 @@ public class TotalFreedomMod extends AeroPlugin as = services.registerService(AntiSpam.class); mbl = services.registerService(MasterBuilderList.class); mbwr = services.registerService(MasterBuilderWorldRestrictions.class); +<<<<<<< HEAD //hwr = services.registerService(HubWorldRestrictions.class); +======= +>>>>>>> d582398f932330853b0456b684654da4c860e831 pl = services.registerService(PlayerList.class); + sh = services.registerService(Shop.class); an = services.registerService(Announcer.class); cm = services.registerService(ChatManager.class); dc = services.registerService(Discord.class); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/blocking/BlockBlocker.java b/src/main/java/me/totalfreedom/totalfreedommod/blocking/BlockBlocker.java index 58a3412b..e5ef0290 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/blocking/BlockBlocker.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/blocking/BlockBlocker.java @@ -115,8 +115,7 @@ public class BlockBlocker extends FreedomService player.getInventory().setItem(player.getInventory().getHeldItemSlot(), new ItemStack(Material.COOKIE, 1)); event.setCancelled(true); break; - } - } + } } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_coins.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_coins.java new file mode 100644 index 00000000..e632a398 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_coins.java @@ -0,0 +1,55 @@ +package me.totalfreedom.totalfreedommod.command; + +import me.totalfreedom.totalfreedommod.config.ConfigEntry; +import me.totalfreedom.totalfreedommod.util.FUtil; +import me.totalfreedom.totalfreedommod.rank.Rank; +import me.totalfreedom.totalfreedommod.shop.ShopData; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +@CommandPermissions(level = Rank.OP, source = SourceType.BOTH) +@CommandParameters(description = "Shows the amount of coins you have or another player", usage = "/ [playername]") +public class Command_coins extends FreedomCommand +{ + + @Override + public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole) + { + if (!ConfigEntry.SHOP_ENABLED.getBoolean()) + { + msg("The shop is currently disabled!", ChatColor.RED); + return true; + } + Player p; + final String prefix = FUtil.colorize(ConfigEntry.SHOP_PREFIX.getString() + " "); + if (args.length > 0) + { + if (getPlayer(args[0]) != null) + { + p = getPlayer(args[0]); + } + else + { + msg(PLAYER_NOT_FOUND); + return true; + } + } + else + { + if (senderIsConsole) + { + msg(prefix + ChatColor.RED + "You are not a player, use /coins "); + return true; + } + else + { + p = playerSender; + } + } + ShopData sd = plugin.sh.getData(p); + msg(prefix + ChatColor.GREEN + (args.length > 0 ? p.getName() + " has " : "You have ") + ChatColor.RED + sd.getCoins() + ChatColor.GREEN + " coins." + " This will be in use shortly."); + return true; + } +} \ No newline at end of file diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_manageshop.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_manageshop.java new file mode 100644 index 00000000..6fd0e8b5 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_manageshop.java @@ -0,0 +1,165 @@ +package me.totalfreedom.totalfreedommod.command; + +import me.totalfreedom.totalfreedommod.config.ConfigEntry; +import me.totalfreedom.totalfreedommod.rank.Rank; +import me.totalfreedom.totalfreedommod.shop.ShopData; +import me.totalfreedom.totalfreedommod.util.FUtil; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +@CommandPermissions(level = Rank.SENIOR_ADMIN, source = SourceType.BOTH) +@CommandParameters(description = "Manage the shop", usage = "/ >", aliases = "ms") +public class Command_manageshop extends FreedomCommand +{ + @Override + public boolean run(final CommandSender sender, final Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole) + { + if (!ConfigEntry.SHOP_ENABLED.getBoolean()) + { + msg("The shop is currently disabled!", ChatColor.RED); + return true; + } + if (!FUtil.isExecutive(sender.getName()) && !sender.getName().equals("CONSOLE")) + { + msg("Only executives can use this command!", ChatColor.RED); + return true; + } + final String prefix = FUtil.colorize(ConfigEntry.SHOP_PREFIX.getString() + " "); + if (args.length > 3) + { + if (args[0].equalsIgnoreCase("coins")) + { + if (getPlayer(args[3]) != null || args[3].equals("all")) + { + Player p = null; + ShopData sd = null; + if (!args[3].equals("all")) + { + p = getPlayer(args[3]); + sd = plugin.sh.getData(p); + } + int newAmount; + int num; + switch (args[1]) + { + case "add": + try + { + num = Math.max(0, Math.min(1000000, Integer.parseInt(args[2]))); + if (!args[3].equals("all")) + { + newAmount = sd.getCoins() + num; + sd.setCoins(newAmount); + plugin.sh.save(sd); + msg(prefix + ChatColor.GREEN + "Gave " + ChatColor.RED + args[2] + ChatColor.GREEN + " coins to " + p.getName() + ", " + p.getName() + " now has " + ChatColor.RED + sd.getCoins() + ChatColor.GREEN + " coins."); + p.sendMessage(prefix + ChatColor.GREEN + sender.getName() + " gave you " + ChatColor.RED + args[2] + ChatColor.GREEN + " coins, you now have " + ChatColor.RED + sd.getCoins() + ChatColor.GREEN + " coins."); + return true; + } + else + { + for (Player player : server.getOnlinePlayers()) + { + sd = plugin.sh.getData(player); + newAmount = sd.getCoins() + num; + sd.setCoins(newAmount); + plugin.sh.save(sd); + player.sendMessage(prefix + ChatColor.GREEN + sender.getName() + " gave you " + ChatColor.RED + args[2] + ChatColor.GREEN + " coins, you now have " + ChatColor.RED + sd.getCoins() + ChatColor.GREEN + " coins."); + } + msg(prefix + ChatColor.GREEN + "Gave " + ChatColor.RED + args[2] + ChatColor.GREEN + " coins to everyone."); + return true; + } + } + catch (NumberFormatException ex) + { + msg("Invalid number: " + args[2], ChatColor.RED); + return true; + } + case "set": + try + { + newAmount = Math.max(0, Math.min(1000000, Integer.parseInt(args[2]))); + if (!args[3].equals("all")) + { + sd.setCoins(newAmount); + plugin.sh.save(sd); + msg(prefix + ChatColor.GREEN + "Set " + p.getName() + "'s coin amount to " + ChatColor.RED + newAmount + ChatColor.GREEN + "."); + p.sendMessage(prefix + ChatColor.GREEN + sender.getName() + " set your coin amount to " + args[2] + ChatColor.GREEN + "."); + return true; + } + else + { + newAmount = Math.max(0, Math.min(1000000, Integer.parseInt(args[2]))); + for (Player player : server.getOnlinePlayers()) + { + sd = plugin.sh.getData(player); + sd.setCoins(newAmount); + plugin.sh.save(sd); + player.sendMessage(prefix + ChatColor.GREEN + sender.getName() + " set your coin amount to " + args[2] + ChatColor.GREEN + "."); + } + msg(prefix + ChatColor.GREEN + "Set everyones's coin amount to " + ChatColor.RED + newAmount + ChatColor.GREEN + "."); + return true; + } + } + catch (NumberFormatException ex) + { + msg("Invalid number: " + args[2], ChatColor.RED); + return true; + } + case "remove": + try + { + num = Math.max(0, Math.min(1000000, Integer.parseInt(args[2]))); + if (!args[3].equals("all")) + { + if (num > sd.getCoins()) + { + msg(prefix + "You can't give a player a negative amount of coins, I'm sorry, you can't put anyone in debt.", ChatColor.RED); + return true; + } + newAmount = sd.getCoins() - num; + sd.setCoins(newAmount); + plugin.sh.save(sd); + msg(prefix + ChatColor.GREEN + "Took " + ChatColor.RED + args[2] + ChatColor.GREEN + " coins from " + p.getName() + ", " + p.getName() + " now has " + ChatColor.RED + sd.getCoins() + ChatColor.GREEN + " coins."); + p.sendMessage(prefix + ChatColor.GREEN + sender.getName() + " took " + ChatColor.RED + args[2] + ChatColor.GREEN + " coins from you, you now have " + ChatColor.RED + sd.getCoins() + ChatColor.GREEN + " coins."); + return true; + } + else + { + for (Player player : server.getOnlinePlayers()) + { + sd = plugin.sh.getData(player); + if (num > sd.getCoins()) + { + sd.setCoins(0); + } + newAmount = sd.getCoins() - num; + sd.setCoins(newAmount); + plugin.sh.save(sd); + player.sendMessage(prefix + ChatColor.GREEN + sender.getName() + " took " + ChatColor.RED + args[2] + ChatColor.GREEN + " coins from you, you now have " + ChatColor.RED + sd.getCoins() + ChatColor.GREEN + " coins."); + } + msg(prefix + ChatColor.GREEN + "Took " + ChatColor.RED + args[2] + ChatColor.GREEN + " coins from everyone."); + return true; + } + } + catch (NumberFormatException ex) + { + msg("Invalid number: " + args[2], ChatColor.RED); + return true; + } + default: + break; + } + } + else + { + msg(FreedomCommand.PLAYER_NOT_FOUND); + return true; + } + } + } + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_nicknyan.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_nicknyan.java index f1f5e8ca..137b754f 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_nicknyan.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_nicknyan.java @@ -35,9 +35,9 @@ public class Command_nicknyan extends FreedomCommand msg("That nickname contains invalid characters."); return true; } - else if (nickPlain.length() < 4 || nickPlain.length() > 30) + else if (nickPlain.length() < 3 || nickPlain.length() > 30) { - msg("Your nickname must be between 4 and 30 characters long."); + msg("Your nickname must be between 3 and 30 characters long."); return true; } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_rainbownick.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_rainbownick.java index 1147c95a..31f93177 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_rainbownick.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_rainbownick.java @@ -29,9 +29,9 @@ public class Command_rainbownick extends FreedomCommand return true; } - if (nickPlain.length() < 4 || nickPlain.length() > 30) + if (nickPlain.length() < 3 || nickPlain.length() > 30) { - msg("Your nickname must be between 4 and 30 characters long."); + msg("Your nickname must be between 3 and 30 characters long."); return true; } @@ -56,4 +56,4 @@ public class Command_rainbownick extends FreedomCommand return true; } -} \ No newline at end of file +} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_toggle.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_toggle.java index 49e10447..2d64d35c 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_toggle.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_toggle.java @@ -39,6 +39,7 @@ public class Command_toggle extends FreedomCommand msg("- unsafeenchs"); msg("- bells"); msg("- armorstands"); + msg("- clearonjoin"); return false; } @@ -171,6 +172,11 @@ public class Command_toggle extends FreedomCommand toggle("The placement of armor stands is", ConfigEntry.ALLOW_ARMOR_STANDS); return true; } + else if (args[0].equalsIgnoreCase("clearonjoin")) + { + toggle("The clearing of inventories on join is", ConfigEntry.ALLOW_CLEAR_ON_JOIN); + return true; + } else { return false; @@ -189,7 +195,7 @@ public class Command_toggle extends FreedomCommand { return Arrays.asList( "waterplace", "fireplace", "lavaplace", "fluidspread", "lavadmg", "firespread", "frostwalk", - "firework", "prelog", "lockdown", "petprotect", "entitywipe", "nonuke", "explosives", "unsafeenchs", "bells", "armorstands"); + "firework", "prelog", "lockdown", "petprotect", "entitywipe", "nonuke", "explosives", "unsafeenchs", "bells", "armorstands", "clearonjoin"); } return Collections.emptyList(); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java b/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java index 682b4c37..7624a1b0 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java @@ -24,7 +24,11 @@ public enum ConfigEntry ALLOW_UNSAFE_ENCHANTMENTS(Boolean.class, "allow.unsafe_enchantments"), ALLOW_BELLS(Boolean.class, "allow.bells"), ALLOW_ARMOR_STANDS(Boolean.class, "allow.armorstands"), +<<<<<<< HEAD ALLOW_MINECARTS (Boolean.class, "allow.minecarts"), +======= + ALLOW_CLEAR_ON_JOIN(Boolean.class, "allow.clearonjoin"), +>>>>>>> d582398f932330853b0456b684654da4c860e831 // BLOCKED_CHATCODES(String.class, "blocked_chatcodes"), // @@ -59,10 +63,16 @@ public enum ConfigEntry DISCORD_SUPER_ROLE_ID(String.class, "discord.super_role_id"), DISCORD_TELNET_ROLE_ID(String.class, "discord.telnet_role_id"), DISCORD_SENIOR_ROLE_ID(String.class, "discord.senior_role_id"), +<<<<<<< HEAD DISCORD_DEVELOPER_ROLE_ID(String.class, "discord.developer_role_id"), DISCORD_EXECUTIVE_ROLE_ID(String.class, "discord.executive_role_id"), DISCORD_SERVER_OWNER_ROLE_ID(String.class, "discord.server_owner_role_id"), +======= + // + SHOP_ENABLED(Boolean.class, "shop.enabled"), + SHOP_PREFIX(String.class, "shop.prefix"), +>>>>>>> d582398f932330853b0456b684654da4c860e831 // ADMINLIST_CLEAN_THESHOLD_HOURS(Integer.class, "adminlist.clean_threshold_hours"), ADMINLIST_CONSOLE_IS_SENIOR(Boolean.class, "adminlist.console_is_senior"), diff --git a/src/main/java/me/totalfreedom/totalfreedommod/fun/ItemFun.java b/src/main/java/me/totalfreedom/totalfreedommod/fun/ItemFun.java index 0a213541..849ad4c6 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/fun/ItemFun.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/fun/ItemFun.java @@ -141,11 +141,14 @@ public class ItemFun extends FreedomService { break; } +<<<<<<< HEAD /*if (player.getWorld().equals(plugin.wm.hubworld.getWorld()) && plugin.hwr.doRestrict(player)) { break; }*/ +======= +>>>>>>> d582398f932330853b0456b684654da4c860e831 Location location = player.getLocation().clone(); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/httpd/module/Module_file.java b/src/main/java/me/totalfreedom/totalfreedommod/httpd/module/Module_file.java new file mode 100644 index 00000000..c8f09c15 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/httpd/module/Module_file.java @@ -0,0 +1,382 @@ +package me.totalfreedom.totalfreedommod.httpd.module; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import me.totalfreedom.totalfreedommod.TotalFreedomMod; +import me.totalfreedom.totalfreedommod.config.ConfigEntry; +import me.totalfreedom.totalfreedommod.httpd.HTTPDaemon; +import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD; +import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD.Response; +import org.apache.commons.lang3.StringUtils; + +/* + * This class was adapted from https://github.com/NanoHttpd/nanohttpd/blob/master/webserver/src/main/java/fi/iki/elonen/SimpleWebServer.java + */ +public class Module_file extends HTTPDModule +{ + + private final File rootDir = new File(ConfigEntry.HTTPD_PUBLIC_FOLDER.getString()); + public static final Map MIME_TYPES = new HashMap<>(); + + static + { + MIME_TYPES.put("css", "text/css"); + MIME_TYPES.put("htm", "text/html"); + MIME_TYPES.put("html", "text/html"); + MIME_TYPES.put("xml", "text/xml"); + MIME_TYPES.put("java", "text/x-java-source, text/java"); + MIME_TYPES.put("txt", "text/plain"); + MIME_TYPES.put("asc", "text/plain"); + MIME_TYPES.put("yml", "text/yaml"); + MIME_TYPES.put("gif", "image/gif"); + MIME_TYPES.put("jpg", "image/jpeg"); + MIME_TYPES.put("jpeg", "image/jpeg"); + MIME_TYPES.put("png", "image/png"); + MIME_TYPES.put("mp3", "audio/mpeg"); + MIME_TYPES.put("m3u", "audio/mpeg-url"); + MIME_TYPES.put("mp4", "video/mp4"); + MIME_TYPES.put("ogv", "video/ogg"); + MIME_TYPES.put("flv", "video/x-flv"); + MIME_TYPES.put("mov", "video/quicktime"); + MIME_TYPES.put("swf", "application/x-shockwave-flash"); + MIME_TYPES.put("js", "application/javascript"); + MIME_TYPES.put("pdf", "application/pdf"); + MIME_TYPES.put("doc", "application/msword"); + MIME_TYPES.put("ogg", "application/x-ogg"); + MIME_TYPES.put("zip", "application/octet-stream"); + MIME_TYPES.put("exe", "application/octet-stream"); + MIME_TYPES.put("class", "application/octet-stream"); + } + + public Module_file(TotalFreedomMod plugin, NanoHTTPD.HTTPSession session) + { + super(plugin, session); + } + + private File getRootDir() + { + return rootDir; + } + + private String encodeUri(String uri) + { + String newUri = ""; + StringTokenizer st = new StringTokenizer(uri, "/ ", true); + while (st.hasMoreTokens()) + { + String tok = st.nextToken(); + if (tok.equals("/")) + { + newUri += "/"; + } + else if (tok.equals(" ")) + { + newUri += "%20"; + } + else + { + try + { + newUri += URLEncoder.encode(tok, "UTF-8"); + } + catch (UnsupportedEncodingException ignored) + { + } + } + } + return newUri; + } + + public Response serveFile(String uri, Map params, File homeDir) + { + Response res = null; + + // Make sure we won't die of an exception later + if (!homeDir.isDirectory()) + { + res = new Response(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "INTERNAL ERRROR: serveFile(): given homeDir is not a directory."); + } + + if (res == null) + { + // Remove URL arguments + uri = uri.trim().replace(File.separatorChar, '/'); + if (uri.indexOf('?') >= 0) + { + uri = uri.substring(0, uri.indexOf('?')); + } + + // Prohibit getting out of current directory + if (uri.startsWith("src/main") || uri.endsWith("src/main") || uri.contains("../")) + { + res = new Response(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: Won't serve ../ for security reasons."); + } + } + + File f = new File(homeDir, uri); + if (res == null && !f.exists()) + { + res = new Response(Response.Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, "Error 404, file not found."); + } + + // List the directory, if necessary + if (res == null && f.isDirectory()) + { + // Browsers get confused without '/' after the + // directory, send a redirect. + if (!uri.endsWith("/")) + { + uri += "/"; + res = new Response(Response.Status.REDIRECT, NanoHTTPD.MIME_HTML, "Redirected: " + uri + + ""); + res.addHeader("Location", uri); + } + + if (res == null) + { + // First try index.html and index.htm + if (new File(f, "index.html").exists()) + { + f = new File(homeDir, uri + "/index.html"); + } + else if (new File(f, "index.htm").exists()) + { + f = new File(homeDir, uri + "/index.htm"); + } + else if (f.canRead()) + { + // No index file, list the directory if it is readable + res = new Response(listDirectory(uri, f)); + } + else + { + res = new Response(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: No directory listing."); + } + } + } + + try + { + if (res == null) + { + // Get MIME type from file name extension, if possible + String mime = null; + int dot = f.getCanonicalPath().lastIndexOf('.'); + if (dot >= 0) + { + mime = MIME_TYPES.get(f.getCanonicalPath().substring(dot + 1).toLowerCase()); + } + if (mime == null) + { + mime = HTTPDaemon.MIME_DEFAULT_BINARY; + } + + // Calculate etag + String etag = Integer.toHexString((f.getAbsolutePath() + f.lastModified() + "" + f.length()).hashCode()); + + final long fileLen = f.length(); + + long startFrom = 0; + long endAt = -1; + final String range = params.get("range"); + if (range != null) + { + final String[] rangeParams = StringUtils.split(range, "="); + if (rangeParams.length >= 2) + { + if ("bytes".equalsIgnoreCase(rangeParams[0])) + { + try + { + int minus = rangeParams[1].indexOf('-'); + if (minus > 0) + { + startFrom = Long.parseLong(rangeParams[1].substring(0, minus)); + endAt = Long.parseLong(rangeParams[1].substring(minus + 1)); + } + } + catch (NumberFormatException ignored) + { + } + } + else if ("tail".equalsIgnoreCase(rangeParams[0])) + { + try + { + final long tailLen = Long.parseLong(rangeParams[1]); + if (tailLen < fileLen) + { + startFrom = fileLen - tailLen - 2; + if (startFrom < 0) + { + startFrom = 0; + } + } + } + catch (NumberFormatException ignored) + { + } + } + } + } + + // Change return code and add Content-Range header when skipping is requested + if (range != null && startFrom >= 0) + { + if (startFrom >= fileLen) + { + res = new Response(Response.Status.RANGE_NOT_SATISFIABLE, NanoHTTPD.MIME_PLAINTEXT, ""); + res.addHeader("Content-Range", "bytes 0-0/" + fileLen); + res.addHeader("ETag", etag); + } + else + { + if (endAt < 0) + { + endAt = fileLen - 1; + } + long newLen = endAt - startFrom + 1; + if (newLen < 0) + { + newLen = 0; + } + + final long dataLen = newLen; + FileInputStream fis = new FileInputStream(f) + { + @Override + public int available() throws IOException + { + return (int)dataLen; + } + }; + fis.skip(startFrom); + + res = new Response(Response.Status.PARTIAL_CONTENT, mime, fis); + res.addHeader("Content-Length", "" + dataLen); + res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" + fileLen); + res.addHeader("ETag", etag); + } + } + else + { + res = new Response(Response.Status.OK, mime, new FileInputStream(f)); + res.addHeader("Content-Length", "" + fileLen); + res.addHeader("ETag", etag); + } + } + } + catch (IOException ioe) + { + res = new Response(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: Reading file failed."); + } + + res.addHeader("Accept-Ranges", "bytes"); // Announce that the file server accepts partial content requestes + return res; + } + + private String listDirectory(String uri, File f) + { + String heading = "Directory " + uri; + String msg = "" + heading + "" + + "

" + heading + "

"; + + String up = null; + if (uri.length() > 1) + { + String u = uri.substring(0, uri.length() - 1); + int slash = u.lastIndexOf('/'); + if (slash >= 0 && slash < u.length()) + { + up = uri.substring(0, slash + 1); + } + } + + List files = Arrays.asList(f.list(new FilenameFilter() + { + @Override + public boolean accept(File dir, String name) + { + return new File(dir, name).isFile(); + } + })); + Collections.sort(files); + List directories = Arrays.asList(f.list(new FilenameFilter() + { + @Override + public boolean accept(File dir, String name) + { + return new File(dir, name).isDirectory(); + } + })); + Collections.sort(directories); + if (up != null || directories.size() + files.size() > 0) + { + msg += "
    "; + if (up != null || directories.size() > 0) + { + msg += "
    "; + if (up != null) + { + msg += "
  • ..
  • "; + } + for (int i = 0; i < directories.size(); i++) + { + String dir = directories.get(i) + "/"; + msg += "
  • " + dir + "
  • "; + } + msg += "
    "; + } + if (files.size() > 0) + { + msg += "
    "; + for (int i = 0; i < files.size(); i++) + { + String file = files.get(i); + + msg += "
  • " + file + ""; + File curFile = new File(f, file); + long len = curFile.length(); + msg += " ("; + if (len < 1024) + { + msg += len + " bytes"; + } + else if (len < 1024 * 1024) + { + msg += len / 1024 + "." + (len % 1024 / 10 % 100) + " KB"; + } + else + { + msg += len / (1024 * 1024) + "." + len % (1024 * 1024) / 10 % 100 + " MB"; + } + msg += ")
  • "; + } + msg += "
    "; + } + msg += "
"; + } + msg += ""; + return msg; + } + + @Override + public Response getResponse() + { + return serveFile(uri, params, getRootDir()); + } +} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/shop/Shop.java b/src/main/java/me/totalfreedom/totalfreedommod/shop/Shop.java new file mode 100644 index 00000000..53a1c388 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/shop/Shop.java @@ -0,0 +1,176 @@ +package me.totalfreedom.totalfreedommod.shop; + +import com.google.common.collect.Maps; +import java.io.File; +import java.util.Collection; +import java.util.Map; +import lombok.Getter; +import me.totalfreedom.totalfreedommod.FreedomService; +import me.totalfreedom.totalfreedommod.TotalFreedomMod; +import me.totalfreedom.totalfreedommod.config.ConfigEntry; +import me.totalfreedom.totalfreedommod.util.FLog; +import me.totalfreedom.totalfreedommod.util.FUtil; +import net.pravian.aero.config.YamlConfig; +import net.pravian.aero.util.Ips; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.player.PlayerQuitEvent; + +public class Shop extends FreedomService +{ + @Getter + public final Map dataMap = Maps.newHashMap(); // ip,dataMap + @Getter + private final File configFolder; + + public Shop(TotalFreedomMod plugin) + { + super(plugin); + + this.configFolder = new File(plugin.getDataFolder(), "shopdata"); + } + + @Override + protected void onStart() + { + dataMap.clear(); + } + + @Override + protected void onStop() + { + for (ShopData sd : dataMap.values()) + { + save(sd); + } + } + + public void save(ShopData data) + { + YamlConfig config = getConfig(data); + data.saveTo(config); + config.save(); + } + + public String getIp(OfflinePlayer player) + { + if (player.isOnline()) + { + return Ips.getIp(player.getPlayer()); + } + + final ShopData entry = getData(player.getName()); + + return (entry == null ? null : entry.getIps().iterator().next()); + } + + public String getShopPrefix() + { + return FUtil.colorize(ConfigEntry.SHOP_PREFIX.getString() + " "); + } + + // May not return null + public ShopData getData(Player player) + { + // Check already loaded + ShopData data = dataMap.get(Ips.getIp(player)); + if (data != null) + { + return data; + } + + // Load data + data = getData(player.getName()); + + // Create data if nonexistent + if (data == null) + { + FLog.info("Creating new shop data entry for " + player.getName()); + + // Create new player + final long unix = FUtil.getUnixTime(); + data = new ShopData(player); + data.addIp(Ips.getIp(player)); + + // Set defaults + data.setCoins(0); + + // Store player + dataMap.put(player.getName().toLowerCase(), data); + + // Save player + YamlConfig config = getConfig(data); + data.saveTo(config); + config.save(); + } + + return data; + } + + // May return null + public ShopData getData(String username) + { + username = username.toLowerCase(); + + // Check if the player is a known player + final File configFile = getConfigFile(username); + if (!configFile.exists()) + { + return null; + } + + // Create and load entry + final ShopData data = new ShopData(username); + data.loadFrom(getConfig(data)); + + if (!data.isValid()) + { + FLog.warning("Could not load shop data entry: " + username + ". Entry is not valid!"); + configFile.delete(); + return null; + } + + // Only store data if the player is online + for (String ip : data.getIps()) + { + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) + { + if (Ips.getIp(onlinePlayer).equals(ip)) + { + dataMap.put(ip, data); + return data; + } + } + } + + return data; + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerQuit(PlayerQuitEvent event) + { + final String ip = Ips.getIp(event.getPlayer()); + dataMap.remove(ip); + } + + public Collection getLoadedData() + { + return dataMap.values(); + } + + protected File getConfigFile(String name) + { + return new File(getConfigFolder(), name + ".yml"); + } + + protected YamlConfig getConfig(ShopData data) + { + final YamlConfig config = new YamlConfig(plugin, getConfigFile(data.getUsername().toLowerCase()), false); + config.load(); + return config; + } +} \ No newline at end of file diff --git a/src/main/java/me/totalfreedom/totalfreedommod/shop/ShopData.java b/src/main/java/me/totalfreedom/totalfreedommod/shop/ShopData.java new file mode 100644 index 00000000..c0403d51 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/shop/ShopData.java @@ -0,0 +1,77 @@ +package me.totalfreedom.totalfreedommod.shop; + +import com.google.common.collect.Lists; +import java.util.Collections; +import java.util.List; +import lombok.Getter; +import lombok.Setter; +import net.pravian.aero.base.ConfigLoadable; +import net.pravian.aero.base.ConfigSavable; +import net.pravian.aero.base.Validatable; +import org.apache.commons.lang3.Validate; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +public class ShopData implements ConfigLoadable, ConfigSavable, Validatable +{ + + @Getter + @Setter + private String username; + private final List ips = Lists.newArrayList(); + @Getter + @Setter + private int coins; + + public ShopData(Player player) + { + this(player.getName()); + } + + public ShopData(String username) + { + this.username = username; + } + + @Override + public void loadFrom(ConfigurationSection cs) + { + this.username = cs.getString("username", username); + this.ips.clear(); + this.ips.addAll(cs.getStringList("ips")); + this.coins = cs.getInt("coins", coins); + } + + @Override + public void saveTo(ConfigurationSection cs) + { + Validate.isTrue(isValid(), "Could not save shop entry: " + username + ". Entry not valid!"); + cs.set("username", username); + cs.set("ips", ips); + cs.set("coins", coins); + } + + public List getIps() + { + return Collections.unmodifiableList(ips); + } + + // IP utils + public boolean addIp(String ip) + { + return ips.contains(ip) ? false : ips.add(ip); + } + + public boolean removeIp(String ip) + { + return ips.remove(ip); + } + + + @Override + public boolean isValid() + { + return username != null + && !ips.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java b/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java index 44a4229b..372a440e 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java @@ -38,7 +38,7 @@ public class FUtil // public static final String SAVED_FLAGS_FILENAME = "savedflags.dat"; // See https://github.com/TotalFreedom/License - None of the listed names may be removed. - public static final List DEVELOPERS = Arrays.asList("Madgeek1450", "Prozza", "WickedGamingUK", "OxLemonxO", "Wild1145", "Catholic_Mario", "Arcaknight", "homeybee"); + public static final List DEVELOPERS = Arrays.asList("Madgeek1450", "Prozza", "WickedGamingUK", "OxLemonxO", "Wild1145", "Catholic_Mario", "Arcaknight", "RealIvan"); public static String DATE_STORAGE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z"; public static final Map CHAT_COLOR_NAMES = new HashMap<>(); public static final List CHAT_COLOR_POOL = Arrays.asList( diff --git a/src/main/java/me/totalfreedom/totalfreedommod/world/HubWorld.java b/src/main/java/me/totalfreedom/totalfreedommod/world/HubWorld.java deleted file mode 100644 index 3578c384..00000000 --- a/src/main/java/me/totalfreedom/totalfreedommod/world/HubWorld.java +++ /dev/null @@ -1,99 +0,0 @@ -package me.totalfreedom.totalfreedommod.world; - -import me.totalfreedom.totalfreedommod.config.ConfigEntry; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.WorldCreator; -import org.bukkit.WorldType; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.entity.Player; - -public final class HubWorld extends CustomWorld -{ - - private static final String GENERATION_PARAMETERS = ConfigEntry.FLATLANDS_GENERATE_PARAMS.getString(); - // - private WorldWeather weather = WorldWeather.OFF; - private WorldTime time = WorldTime.INHERIT; - - public HubWorld() - { - super("hubworld"); - } - - @Override - public void sendToWorld(Player player) - { - super.sendToWorld(player); - } - - @Override - protected World generateWorld() - { - final WorldCreator worldCreator = new WorldCreator(getName()); - worldCreator.generateStructures(false); - worldCreator.type(WorldType.NORMAL); - worldCreator.environment(World.Environment.NORMAL); - worldCreator.generator(new CleanroomChunkGenerator(GENERATION_PARAMETERS)); - - final World world = server.createWorld(worldCreator); - - world.setSpawnFlags(false, false); - world.setSpawnLocation(0, 50, 0); - - final Block welcomeSignBlock = world.getBlockAt(0, 50, 0); - welcomeSignBlock.setType(Material.OAK_SIGN); - org.bukkit.block.Sign welcomeSign = (org.bukkit.block.Sign)welcomeSignBlock.getState(); - - org.bukkit.material.Sign signData = (org.bukkit.material.Sign)welcomeSign.getData(); - signData.setFacingDirection(BlockFace.NORTH); - - welcomeSign.setLine(0, ChatColor.GREEN + "Hub World"); - welcomeSign.setLine(1, ChatColor.DARK_GRAY + "---"); - welcomeSign.setLine(2, ChatColor.YELLOW + "Spawn Point"); - welcomeSign.setLine(3, ChatColor.DARK_GRAY + "---"); - welcomeSign.update(); - - plugin.gr.commitGameRules(); - return world; - } - - public WorldWeather getWeatherMode() - { - return weather; - } - - public void setWeatherMode(final WorldWeather weatherMode) - { - this.weather = weatherMode; - - try - { - weatherMode.setWorldToWeather(getWorld()); - } - catch (Exception ex) - { - } - } - - public WorldTime getTimeOfDay() - { - return time; - } - - public void setTimeOfDay(final WorldTime timeOfDay) - { - this.time = timeOfDay; - - try - { - timeOfDay.setWorldToTime(getWorld()); - } - catch (Exception ex) - { - } - } - -} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/world/WorldManager.java b/src/main/java/me/totalfreedom/totalfreedommod/world/WorldManager.java index e2a3286d..ff0ca7f5 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/world/WorldManager.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/world/WorldManager.java @@ -23,7 +23,10 @@ public class WorldManager extends FreedomService public Flatlands flatlands; public AdminWorld adminworld; public MasterBuilderWorld masterBuilderWorld; +<<<<<<< HEAD //public HubWorld hubworld; +======= +>>>>>>> d582398f932330853b0456b684654da4c860e831 public WorldManager(TotalFreedomMod plugin) { @@ -32,7 +35,10 @@ public class WorldManager extends FreedomService this.flatlands = new Flatlands(); this.adminworld = new AdminWorld(); this.masterBuilderWorld = new MasterBuilderWorld(); +<<<<<<< HEAD //this.hubworld = new HubWorld(); +======= +>>>>>>> d582398f932330853b0456b684654da4c860e831 } @Override @@ -41,7 +47,10 @@ public class WorldManager extends FreedomService flatlands.getWorld(); adminworld.getWorld(); masterBuilderWorld.getWorld(); +<<<<<<< HEAD //hubworld.getWorld(); +======= +>>>>>>> d582398f932330853b0456b684654da4c860e831 // Disable weather if (ConfigEntry.DISABLE_WEATHER.getBoolean()) @@ -62,7 +71,10 @@ public class WorldManager extends FreedomService flatlands.getWorld().save(); adminworld.getWorld().save(); masterBuilderWorld.getWorld().save(); +<<<<<<< HEAD //hubworld.getWorld().save(); +======= +>>>>>>> d582398f932330853b0456b684654da4c860e831 } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @@ -113,10 +125,13 @@ public class WorldManager extends FreedomService { return; } +<<<<<<< HEAD /*else if (event.getWorld().equals(hubworld.getWorld()) && hubworld.getWeatherMode() != WorldWeather.OFF) { return; }*/ +======= +>>>>>>> d582398f932330853b0456b684654da4c860e831 } catch (Exception ex) { @@ -141,10 +156,13 @@ public class WorldManager extends FreedomService { return; } +<<<<<<< HEAD /*else if (event.getWorld().equals(hubworld.getWorld()) && hubworld.getWeatherMode() != WorldWeather.OFF) { return; }*/ +======= +>>>>>>> d582398f932330853b0456b684654da4c860e831 } catch (Exception ex) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 2abba961..fadc88fd 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -57,6 +57,7 @@ discord: telnet_role_id: '' # Senior Admin role ID senior_role_id: '' +<<<<<<< HEAD # Developer role ID developer_role_id: '' # Executive Admin role ID @@ -64,6 +65,16 @@ discord: # Owner role ID server_owner_role_id: '' +======= + +# The shop +shop: + # Enable the shop + enabled: true + + # Shop prefix + prefix: '&7&l[&8&lTF Shop&7&l]' +>>>>>>> d582398f932330853b0456b684654da4c860e831 # Admin list adminlist: @@ -116,7 +127,11 @@ allow: unsafe_enchantments: true bells: true armorstands: false +<<<<<<< HEAD minecarts: false +======= + clearonjoin: false +>>>>>>> d582398f932330853b0456b684654da4c860e831 # Blocked commands: #