1
0
mirror of https://e.coding.net/circlecloud/QuickShop.git synced 2024-11-25 02:28:54 +00:00

feat: 使用新类库处理命令 添加1.9+虚拟悬浮物

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2016-09-14 02:05:58 +08:00
parent db7e6c0f4c
commit 0c9a014c13
15 changed files with 697 additions and 436 deletions

BIN
lib/ProtocolLib-4.1.jar Normal file

Binary file not shown.

25
pom.xml
View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.maxgamer</groupId> <groupId>org.maxgamer</groupId>
<artifactId>QuickShop</artifactId> <artifactId>QuickShop</artifactId>
<version>1.9.3</version> <version>1.9.4</version>
<description>快捷商店重置版本...</description> <description>快捷商店重置版本...</description>
<build> <build>
<finalName>${project.name}</finalName> <finalName>${project.name}</finalName>
@ -31,12 +31,12 @@
<minimizeJar>true</minimizeJar> <minimizeJar>true</minimizeJar>
<artifactSet> <artifactSet>
<includes> <includes>
<include>cn.citycraft:PluginHelper</include> <include>pw.yumc:YumCore</include>
</includes> </includes>
</artifactSet> </artifactSet>
<relocations> <relocations>
<relocation> <relocation>
<pattern>cn.citycraft.PluginHelper</pattern> <pattern>pw.yumc.YumCore</pattern>
<shadedPattern>${project.groupId}.${project.artifactId}</shadedPattern> <shadedPattern>${project.groupId}.${project.artifactId}</shadedPattern>
</relocation> </relocation>
</relocations> </relocations>
@ -60,9 +60,9 @@
<env.GIT_COMMIT>DEBUG</env.GIT_COMMIT> <env.GIT_COMMIT>DEBUG</env.GIT_COMMIT>
<update.description>&amp;a全新版本 &amp;c虚拟悬浮物(橙子提供 对 就是那个汉化COI的逗比)&amp;e7老板修复逗比BUG...</update.description> <update.description>&amp;a全新版本 &amp;c虚拟悬浮物(橙子提供 对 就是那个汉化COI的逗比)&amp;e7老板修复逗比BUG...</update.description>
<update.changes> <update.changes>
&amp;b1.9.4 - &amp;a1.9+兼容虚拟悬浮物...;
&amp;b1.9.3 - &amp;a木牌第一行显示配置文件的guititle内容...; &amp;b1.9.3 - &amp;a木牌第一行显示配置文件的guititle内容...;
&amp;b1.9.2 - &amp;c修复一个在删除商店时导致的报错...; &amp;b1.9.2 - &amp;c修复一个在删除商店时导致的报错...;
&amp;b1.9.1 - &amp;c修复同一个玩家的商店直接漏洞不能传递的问题...;
</update.changes> </update.changes>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
@ -84,7 +84,7 @@
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<type>jar</type> <type>jar</type>
<version>1.9-R0.1-SNAPSHOT</version> <version>1.10.2-R0.1-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.milkbowl.vault</groupId> <groupId>net.milkbowl.vault</groupId>
@ -93,8 +93,8 @@
<version>1.5.6</version> <version>1.5.6</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cn.citycraft</groupId> <groupId>pw.yumc</groupId>
<artifactId>PluginHelper</artifactId> <artifactId>YumCore</artifactId>
<type>jar</type> <type>jar</type>
<version>1.0</version> <version>1.0</version>
</dependency> </dependency>
@ -113,9 +113,16 @@
<dependency> <dependency>
<groupId>com.comphenix.protocol</groupId> <groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId> <artifactId>ProtocolLib</artifactId>
<version>3.6.5-SNAPSHOT</version> <version>3.6.5</version>
<scope>system</scope> <scope>system</scope>
<systemPath>${project.basedir}/lib/ProtocolLib-3.6.5-SNAPSHOT.jar</systemPath> <systemPath>${project.basedir}/lib/ProtocolLib-3.6.5.jar</systemPath>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/ProtocolLib-4.1.jar</systemPath>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -24,30 +24,32 @@ import org.maxgamer.QuickShop.Shop.ShopChunk;
import org.maxgamer.QuickShop.Shop.ShopType; import org.maxgamer.QuickShop.Shop.ShopType;
import org.maxgamer.QuickShop.Util.MsgUtil; import org.maxgamer.QuickShop.Util.MsgUtil;
import cn.citycraft.PluginHelper.commands.HandlerCommand; import pw.yumc.YumCore.bukkit.P;
import cn.citycraft.PluginHelper.commands.HandlerCommands; import pw.yumc.YumCore.commands.CommandArgument;
import cn.citycraft.PluginHelper.commands.HandlerDescription; import pw.yumc.YumCore.commands.CommandExecutor;
import cn.citycraft.PluginHelper.commands.InvokeCommandEvent; import pw.yumc.YumCore.commands.CommandHelpParse;
import cn.citycraft.PluginHelper.commands.InvokeSubCommand; import pw.yumc.YumCore.commands.CommandManager;
import cn.citycraft.PluginHelper.utils.StringUtil; import pw.yumc.YumCore.commands.annotation.Cmd;
import pw.yumc.YumCore.commands.annotation.Cmd.Executor;
import pw.yumc.YumCore.commands.annotation.Help;
import pw.yumc.YumCore.kit.StrKit;
public class QuickShopCommands implements HandlerCommands, HandlerDescription { public class QuickShopCommands implements CommandExecutor, CommandHelpParse {
QuickShop plugin; QuickShop plugin = P.getPlugin();
public QuickShopCommands(final QuickShop plugin) { public QuickShopCommands() {
this.plugin = plugin; new CommandManager("qs", this).setHelpParse(this);
final InvokeSubCommand ics = new InvokeSubCommand(plugin, "qs");
ics.registerCommands(this);
ics.setHandlerDescription(this);
} }
@HandlerCommand(name = "buy", aliases = { "b" }, permission = "quickshop.create.buy", onlyPlayerExecutable = true, description = "command.description.buy") @Cmd(aliases = "b", permission = "quickshop.create.buy", executor = Executor.PLAYER)
public void buy(final InvokeCommandEvent e) { @Help("command.description.buy")
public void buy(final CommandArgument e) {
changeShopType(e.getSender(), ShopType.BUYING); changeShopType(e.getSender(), ShopType.BUYING);
} }
@HandlerCommand(name = "clean", aliases = "c", permission = "quickshop.clean", description = "command.description.clean") @Cmd(aliases = "c", permission = "quickshop.clean")
public void clean(final InvokeCommandEvent e) { @Help("command.description.clean")
public void clean(final CommandArgument e) {
final CommandSender sender = e.getSender(); final CommandSender sender = e.getSender();
sender.sendMessage(MsgUtil.p("command.cleaning")); sender.sendMessage(MsgUtil.p("command.cleaning"));
final Iterator<Shop> shIt = plugin.getShopManager().getShopIterator(); final Iterator<Shop> shIt = plugin.getShopManager().getShopIterator();
@ -71,8 +73,9 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
sender.sendMessage(MsgUtil.p("command.cleaned", "" + i)); sender.sendMessage(MsgUtil.p("command.cleaned", "" + i));
} }
@HandlerCommand(name = "empty", aliases = "e", permission = "quickshop.empty", description = "command.description.empty") @Cmd(aliases = "e", permission = "quickshop.empty")
public void empty(final InvokeCommandEvent e) { @Help("command.description.empty")
public void empty(final CommandArgument e) {
final CommandSender sender = e.getSender(); final CommandSender sender = e.getSender();
final BlockIterator bIt = new BlockIterator((Player) sender, 10); final BlockIterator bIt = new BlockIterator((Player) sender, 10);
while (bIt.hasNext()) { while (bIt.hasNext()) {
@ -93,8 +96,9 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
return; return;
} }
@HandlerCommand(name = "export", minimumArguments = 1, possibleArguments = "[mysql|sqlite]", permission = "quickshop.export", description = "command.description.export") @Cmd(minimumArguments = 1, permission = "quickshop.export")
public void export(final InvokeCommandEvent e) { @Help(value = "command.description.export", possibleArguments = "[mysql|sqlite]")
public void export(final CommandArgument e) {
final CommandSender sender = e.getSender(); final CommandSender sender = e.getSender();
final String type = e.getArgs()[0].toLowerCase(); final String type = e.getArgs()[0].toLowerCase();
if (type.startsWith("mysql")) { if (type.startsWith("mysql")) {
@ -144,10 +148,11 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
} }
} }
@HandlerCommand(name = "find", aliases = "f", minimumArguments = 2, onlyPlayerExecutable = true, permission = "quickshop.find", description = "command.description.find") @Cmd(aliases = "f", minimumArguments = 2, permission = "quickshop.find", executor = Executor.PLAYER)
public void find(final InvokeCommandEvent e) { @Help("command.description.find")
public void find(final CommandArgument e) {
final CommandSender sender = e.getSender(); final CommandSender sender = e.getSender();
String lookFor = StringUtil.consolidateStrings(e.getArgs(), 0); String lookFor = StrKit.consolidateStrings(e.getArgs(), 0);
lookFor = lookFor.toLowerCase(); lookFor = lookFor.toLowerCase();
final Player p = (Player) sender; final Player p = (Player) sender;
final Location loc = p.getEyeLocation().clone(); final Location loc = p.getEyeLocation().clone();
@ -182,13 +187,9 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
return; return;
} }
@Override @Cmd(aliases = "i", permission = "quickshop.info")
public String handler(final String arg0) { @Help("command.description.info")
return MsgUtil.p(arg0); public void info(final CommandArgument e) {
}
@HandlerCommand(name = "info", aliases = "i", permission = "quickshop.info", description = "command.description.info")
public void info(final InvokeCommandEvent e) {
final CommandSender sender = e.getSender(); final CommandSender sender = e.getSender();
int buying, selling, doubles, chunks, worlds, unlimited; int buying, selling, doubles, chunks, worlds, unlimited;
buying = selling = doubles = chunks = worlds = unlimited = 0; buying = selling = doubles = chunks = worlds = unlimited = 0;
@ -223,8 +224,14 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
sender.sendMessage(MsgUtil.p("info.canclean", nostock)); sender.sendMessage(MsgUtil.p("info.canclean", nostock));
} }
@HandlerCommand(name = "price", aliases = "p", minimumArguments = 1, onlyPlayerExecutable = true, possibleArguments = "<价格>", permission = "quickshop.create.changeprice", description = "command.description.price") @Override
public void price(final InvokeCommandEvent e) { public String parse(final String str) {
return MsgUtil.p(str);
}
@Cmd(aliases = "p", minimumArguments = 1, permission = "quickshop.create.changeprice")
@Help(value = "command.description.price", possibleArguments = "<价格>")
public void price(final CommandArgument e) {
final CommandSender sender = e.getSender(); final CommandSender sender = e.getSender();
final Player p = (Player) sender; final Player p = (Player) sender;
double price; double price;
@ -294,8 +301,9 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
return; return;
} }
@HandlerCommand(name = "refill", minimumArguments = 1, possibleArguments = "<数量>", permission = "quickshop.refill", description = "command.description.refill") @Cmd(minimumArguments = 1, permission = "quickshop.refill", executor = Executor.PLAYER)
public void refill(final InvokeCommandEvent e) { @Help(value = "command.description.refill", possibleArguments = "<数量>")
public void refill(final CommandArgument e) {
final CommandSender sender = e.getSender(); final CommandSender sender = e.getSender();
int add; int add;
try { try {
@ -318,18 +326,19 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
return; return;
} }
@HandlerCommand(name = "reload", permission = "quickshop.reload", description = "command.description.reload") @Cmd(permission = "quickshop.reload")
public void reload(final InvokeCommandEvent e) { @Help("command.description.reload")
public void reload(final CommandArgument e) {
final CommandSender sender = e.getSender(); final CommandSender sender = e.getSender();
sender.sendMessage(MsgUtil.p("command.reloading")); sender.sendMessage(MsgUtil.p("command.reloading"));
plugin.reloadConfig(); plugin.reloadConfig();
Bukkit.getPluginManager().disablePlugin(plugin); Bukkit.getPluginManager().disablePlugin(plugin);
Bukkit.getPluginManager().enablePlugin(plugin); Bukkit.getPluginManager().enablePlugin(plugin);
return;
} }
@HandlerCommand(name = "remove", aliases = "r", onlyPlayerExecutable = true, permission = "quickshop.delete", description = "command.description.remove") @Cmd(aliases = "r", permission = "quickshop.delete", executor = Executor.PLAYER)
public void remove(final InvokeCommandEvent e) { @Help("command.description.remove")
public void remove(final CommandArgument e) {
final Player p = (Player) e.getSender(); final Player p = (Player) e.getSender();
final BlockIterator bIt = new BlockIterator(p, 10); final BlockIterator bIt = new BlockIterator(p, 10);
while (bIt.hasNext()) { while (bIt.hasNext()) {
@ -348,13 +357,15 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
p.sendMessage(ChatColor.RED + "未找到商店!"); p.sendMessage(ChatColor.RED + "未找到商店!");
} }
@HandlerCommand(name = "sell", aliases = { "s" }, permission = "quickshop.create.sell", onlyPlayerExecutable = true, description = "command.description.sell") @Cmd(aliases = "s", permission = "quickshop.create.sell")
public void sell(final InvokeCommandEvent e) { @Help("command.description.sell")
public void sell(final CommandArgument e) {
changeShopType(e.getSender(), ShopType.SELLING); changeShopType(e.getSender(), ShopType.SELLING);
} }
@HandlerCommand(name = "setowner", aliases = "so", onlyPlayerExecutable = true, minimumArguments = 1, permission = "quickshop.setowner", description = "command.description.setowner") @Cmd(aliases = "so", minimumArguments = 1, permission = "quickshop.setowner", executor = Executor.PLAYER)
public void setowner(final InvokeCommandEvent e) { @Help("command.description.setowner")
public void setowner(final CommandArgument e) {
final CommandSender sender = e.getSender(); final CommandSender sender = e.getSender();
final String owner = e.getArgs()[0]; final String owner = e.getArgs()[0];
final BlockIterator bIt = new BlockIterator((Player) sender, 10); final BlockIterator bIt = new BlockIterator((Player) sender, 10);
@ -369,11 +380,11 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
} }
} }
sender.sendMessage(MsgUtil.p("not-looking-at-shop")); sender.sendMessage(MsgUtil.p("not-looking-at-shop"));
return;
} }
@HandlerCommand(name = "unlimited", onlyPlayerExecutable = true, permission = "quickshop.unlimited", description = "command.description.unlimited") @Cmd(permission = "quickshop.unlimited", executor = Executor.PLAYER)
public void unlimited(final InvokeCommandEvent e) { @Help("command.description.unlimited")
public void unlimited(final CommandArgument e) {
final CommandSender sender = e.getSender(); final CommandSender sender = e.getSender();
final BlockIterator bIt = new BlockIterator((Player) sender, 10); final BlockIterator bIt = new BlockIterator((Player) sender, 10);
while (bIt.hasNext()) { while (bIt.hasNext()) {
@ -387,7 +398,6 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
} }
} }
sender.sendMessage(MsgUtil.p("not-looking-at-shop")); sender.sendMessage(MsgUtil.p("not-looking-at-shop"));
return;
} }
private void changeShopType(final CommandSender sender, final ShopType shopType) { private void changeShopType(final CommandSender sender, final ShopType shopType) {

View File

@ -9,10 +9,12 @@ import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.maxgamer.QuickShop.QuickShop; import org.maxgamer.QuickShop.QuickShop;
import org.maxgamer.QuickShop.Shop.FakeItem; import org.maxgamer.QuickShop.Shop.Item.FakeItem_17;
import org.maxgamer.QuickShop.Shop.Item.FakeItem_18_110;
import cn.citycraft.PluginHelper.config.FileConfig; import pw.yumc.YumCore.bukkit.Log;
import cn.citycraft.PluginHelper.tellraw.FancyMessage; import pw.yumc.YumCore.config.FileConfig;
import pw.yumc.YumCore.tellraw.Tellraw;
public class ConfigManager { public class ConfigManager {
private boolean enableMagicLib = false; private boolean enableMagicLib = false;
@ -88,23 +90,31 @@ public class ConfigManager {
if (config.getBoolean("fakeitem", true)) { if (config.getBoolean("fakeitem", true)) {
try { try {
plugin.getLogger().info("启用虚拟悬浮物 尝试启动中..."); plugin.getLogger().info("启用虚拟悬浮物 尝试启动中...");
FakeItem.register(plugin); FakeItem_18_110.register(plugin);
plugin.getLogger().info("虚拟悬浮物功能测试正常..."); plugin.getLogger().info("虚拟悬浮物功能测试正常(1.8-1.10.2)...");
fakeItem = true; fakeItem = true;
} catch (final Error | Exception e) { } catch (final Throwable e) {
Log.debug(e);
try {
FakeItem_17.register(plugin);
plugin.getLogger().info("虚拟悬浮物功能测试正常(1.7)...");
fakeItem = true;
} catch (final Throwable e2) {
plugin.getLogger().warning("+========================================="); plugin.getLogger().warning("+=========================================");
plugin.getLogger().warning("| 警告: 启动虚拟物品失败 使用原版悬浮物品..."); plugin.getLogger().warning("| 警告: 启动虚拟物品失败 使用原版悬浮物品...");
plugin.getLogger().warning("+========================================="); plugin.getLogger().warning("+=========================================");
Log.debug(e2);
}
} }
} }
if (config.getBoolean("usemagiclib", true)) { if (config.getBoolean("usemagiclib", true)) {
try { try {
plugin.getLogger().info("启用魔改库 尝试启动中..."); plugin.getLogger().info("启用魔改库 尝试启动中...");
final FancyMessage fm = FancyMessage.newFM("test"); final Tellraw fm = Tellraw.create("test");
fm.then("item").itemTooltip(new ItemStack(Material.DIAMOND_SWORD)); fm.then("item").item(new ItemStack(Material.DIAMOND_SWORD));
fm.then("link").link("ci.citycraft.cn"); fm.then("link").link("yumc.pw");
fm.then("suggest").suggest("qs help"); fm.then("suggest").suggest("qs help");
fm.toJSONString(); fm.toJsonString();
plugin.getLogger().info("魔改库功能测试正常..."); plugin.getLogger().info("魔改库功能测试正常...");
this.enableMagicLib = true; this.enableMagicLib = true;
} catch (final Error | Exception e) { } catch (final Error | Exception e) {

View File

@ -8,12 +8,12 @@ import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Iterator;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
@ -51,9 +51,9 @@ import org.maxgamer.QuickShop.Util.Util;
import org.maxgamer.QuickShop.Watcher.ItemWatcher; import org.maxgamer.QuickShop.Watcher.ItemWatcher;
import org.maxgamer.QuickShop.Watcher.LogWatcher; import org.maxgamer.QuickShop.Watcher.LogWatcher;
import cn.citycraft.PluginHelper.config.FileConfig; import pw.yumc.YumCore.config.FileConfig;
import cn.citycraft.PluginHelper.utils.LocalUtil; import pw.yumc.YumCore.misc.L10N;
import cn.citycraft.PluginHelper.utils.VersionChecker; import pw.yumc.YumCore.update.SubscribeTask;
public class QuickShop extends JavaPlugin { public class QuickShop extends JavaPlugin {
/** 初始化 QuickShop 的接口 */ /** 初始化 QuickShop 的接口 */
@ -151,33 +151,6 @@ public class QuickShop extends JavaPlugin {
} }
public void loadShop() { public void loadShop() {
if (!LocalUtil.isInit()) {
this.getLogger().warning("本地化工具尚未初始化完成 商店汉化信息将在稍后刷新...");
this.getServer().getScheduler().runTaskAsynchronously(this, new Runnable() {
@Override
public void run() {
int error = 0;
try {
while (!LocalUtil.isInit()) {
try {
Thread.sleep(500);
} catch (final InterruptedException e) {
}
}
getLogger().info("本地化工具载入完成 刷新汉化信息...");
final Iterator<Shop> shops = shopManager.getShopIterator();
while (shops.hasNext()) {
shops.next().onClick();
}
} catch (final Exception e) {
error++;
}
if (error != 0) {
getLogger().info("信息刷新完成 期间发生 " + error + " 个错误 已忽略(不是BUG 无需反馈)...");
}
}
});
}
/* 从数据库载入商店信息到内存 */ /* 从数据库载入商店信息到内存 */
int count = 0; // 商店个数 int count = 0; // 商店个数
int unload = 0; int unload = 0;
@ -289,7 +262,6 @@ public class QuickShop extends JavaPlugin {
return; return;
} }
configManager = new ConfigManager(this); configManager = new ConfigManager(this);
LocalUtil.init(this);
// Initialize Util // Initialize Util
Util.initialize(); Util.initialize();
// Create the shop manager. // Create the shop manager.
@ -359,26 +331,27 @@ public class QuickShop extends JavaPlugin {
} }
// Command handlers // Command handlers
new QuickShopCommands(this); new QuickShopCommands();
if (configManager.getFindDistance() > 100) { if (configManager.getFindDistance() > 100) {
getLogger().warning("商店查找半径过大 可能导致服务器Lag! 推荐使用低于 100 的配置!"); getLogger().warning("商店查找半径过大 可能导致服务器Lag! 推荐使用低于 100 的配置!");
} }
this.getLogger().info("载入完成! 版本: " + this.getDescription().getVersion() + " 重制 by 喵♂呜"); this.getLogger().info("载入完成! 版本: " + this.getDescription().getVersion() + " 重制 by 喵♂呜");
new VersionChecker(this); new SubscribeTask();
} }
@Override @Override
public void onLoad() { public void onLoad() {
instance = this; instance = this;
config = new FileConfig(this); config = new FileConfig();
MsgUtil.init(this); MsgUtil.init(this);
L10N.getItemName(new ItemStack(Material.AIR));
} }
/** Reloads QuickShops config */ /** Reloads QuickShops config */
@Override @Override
public void reloadConfig() { public void reloadConfig() {
config.reload(); config.reload();
LocalUtil.reload(this); L10N.reload();
} }
} }

View File

@ -5,6 +5,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -17,11 +18,13 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.maxgamer.QuickShop.QuickShop; import org.maxgamer.QuickShop.QuickShop;
import org.maxgamer.QuickShop.Shop.Item.DisplayItem;
import org.maxgamer.QuickShop.Shop.Item.FakeItem_17;
import org.maxgamer.QuickShop.Shop.Item.NormalItem;
import org.maxgamer.QuickShop.Util.MsgUtil; import org.maxgamer.QuickShop.Util.MsgUtil;
import org.maxgamer.QuickShop.Util.Util; import org.maxgamer.QuickShop.Util.Util;
import cn.citycraft.PluginHelper.kit.P; import pw.yumc.YumCore.bukkit.P;
import cn.citycraft.PluginHelper.kit.PluginKit;
public class ContainerShop implements Shop { public class ContainerShop implements Shop {
private final QuickShop plugin = (QuickShop) P.instance; private final QuickShop plugin = (QuickShop) P.instance;
@ -53,13 +56,7 @@ public class ContainerShop implements Shop {
this.owner = owner; this.owner = owner;
this.item = item.clone(); this.item = item.clone();
this.item.setAmount(1); this.item.setAmount(1);
if (plugin.getConfigManager().isDisplay()) { this.displayItem = DisplayItem.create(this);
if (plugin.getConfigManager().isFakeItem()) {
this.displayItem = new FakeItem(this, this.getItem());
} else {
this.displayItem = new NormalItem(this, this.getItem());
}
}
this.shopType = ShopType.SELLING; this.shopType = ShopType.SELLING;
} }
@ -360,7 +357,7 @@ public class ContainerShop implements Shop {
*/ */
@Override @Override
public List<Sign> getSigns() { public List<Sign> getSigns() {
final ArrayList<Sign> signs = new ArrayList<Sign>(1); final ArrayList<Sign> signs = new ArrayList<>(1);
if (this.getLocation().getWorld() == null) { if (this.getLocation().getWorld() == null) {
return signs; return signs;
} }
@ -518,7 +515,7 @@ public class ContainerShop implements Shop {
this.buy(p, -amount); this.buy(p, -amount);
} }
// Items to drop on floor // Items to drop on floor
final ArrayList<ItemStack> floor = new ArrayList<ItemStack>(5); final ArrayList<ItemStack> floor = new ArrayList<>(5);
final Inventory pInv = p.getInventory(); final Inventory pInv = p.getInventory();
if (this.isUnlimited()) { if (this.isUnlimited()) {
final ItemStack item = this.item.clone(); final ItemStack item = this.item.clone();
@ -604,7 +601,7 @@ public class ContainerShop implements Shop {
} }
final ContainerShop shop = this; final ContainerShop shop = this;
// 1.9不能异步修改木牌 // 1.9不能异步修改木牌
PluginKit.runTask(new Runnable() { Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override @Override
public void run() { public void run() {
final String[] lines = new String[4]; final String[] lines = new String[4];
@ -637,7 +634,7 @@ public class ContainerShop implements Shop {
} }
final List<Sign> signs = this.getSigns(); final List<Sign> signs = this.getSigns();
// 1.9不能异步修改木牌 // 1.9不能异步修改木牌
PluginKit.runTask(new Runnable() { Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override @Override
public void run() { public void run() {
for (final Sign sign : signs) { for (final Sign sign : signs) {
@ -657,7 +654,15 @@ public class ContainerShop implements Shop {
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder("商店 " + (loc.getWorld() == null ? "世界尚未载入" : "坐标: " + loc.getWorld().getName()) + "(" + loc.getBlockX() + ", " + loc.getBlockY() + ", " + loc.getBlockZ() + ")"); final StringBuilder sb = new StringBuilder("商店 "
+ (loc.getWorld() == null ? "世界尚未载入" : "坐标: " + loc.getWorld().getName())
+ "("
+ loc.getBlockX()
+ ", "
+ loc.getBlockY()
+ ", "
+ loc.getBlockZ()
+ ")");
sb.append(" 所有者: " + getOwner()); sb.append(" 所有者: " + getOwner());
if (isUnlimited()) { if (isUnlimited()) {
sb.append(" 无限模式: true"); sb.append(" 无限模式: true");
@ -697,7 +702,7 @@ public class ContainerShop implements Shop {
final boolean trans = Util.isTransparent(getLocation().clone().add(0.5, 1.2, 0.5).getBlock().getType()); final boolean trans = Util.isTransparent(getLocation().clone().add(0.5, 1.2, 0.5).getBlock().getType());
if (trans && this.getDisplayItem() == null) { if (trans && this.getDisplayItem() == null) {
if (plugin.getConfigManager().isFakeItem()) { if (plugin.getConfigManager().isFakeItem()) {
this.displayItem = new FakeItem(this, this.getItem()); this.displayItem = new FakeItem_17(this, this.getItem());
} else { } else {
this.displayItem = new NormalItem(this, this.getItem()); this.displayItem = new NormalItem(this, this.getItem());
} }

View File

@ -1,44 +0,0 @@
package org.maxgamer.QuickShop.Shop;
import org.bukkit.Location;
import org.bukkit.entity.Item;
/**
* @author Netherfoam A display item, that spawns a block above the chest and
* cannot be interacted with.
*/
public interface DisplayItem {
/**
* 获得悬浮物地点
*
* @return 获得悬浮地点
*/
public Location getDisplayLocation();
/**
* @return {@link Item}
*/
public Item getItem();
/**
* 移除悬浮物
*/
public void remove();
/**
* 移除多余物品
*
* @return
*/
public boolean removeDupe();
/**
* 更新悬浮物
*/
public void respawn();
/**
* 刷出悬浮物
*/
public void spawn();
}

View File

@ -0,0 +1,70 @@
package org.maxgamer.QuickShop.Shop.Item;
import org.bukkit.Location;
import org.bukkit.entity.Item;
import org.maxgamer.QuickShop.QuickShop;
import org.maxgamer.QuickShop.Shop.ContainerShop;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.bukkit.P;
/**
* @author Netherfoam A display item, that spawns a block above the chest and
* cannot be interacted with.
*/
public abstract class DisplayItem {
public static QuickShop plugin = P.getPlugin();
public static DisplayItem create(final ContainerShop shop) {
if (plugin.getConfigManager().isDisplay()) {
if (plugin.getConfigManager().isFakeItem()) {
try {
return new FakeItem_18_110(shop, shop.getItem());
} catch (final Throwable e) {
Log.debug(e);
try {
return new FakeItem_17(shop, shop.getItem());
} catch (final Throwable e2) {
Log.debug(e2);
return new NormalItem(shop, shop.getItem());
}
}
}
}
return null;
}
/**
* 获得悬浮物地点
*
* @return 获得悬浮地点
*/
public abstract Location getDisplayLocation();
/**
* @return {@link Item}
*/
public abstract Item getItem();
/**
* 移除悬浮物
*/
public abstract void remove();
/**
* 移除多余物品
*
* @return
*/
public abstract boolean removeDupe();
/**
* 更新悬浮物
*/
public abstract void respawn();
/**
* 刷出悬浮物
*/
public abstract void spawn();
}

View File

@ -1,4 +1,4 @@
package org.maxgamer.QuickShop.Shop; package org.maxgamer.QuickShop.Shop.Item;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -13,6 +13,7 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import org.maxgamer.QuickShop.Shop.ContainerShop;
import com.comphenix.protocol.PacketType; import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.ProtocolLibrary;
@ -28,9 +29,9 @@ import com.comphenix.protocol.wrappers.WrappedWatchableObject;
* @author 橙子(chengzi) * @author 橙子(chengzi)
* @version 1.0.1 * @version 1.0.1
*/ */
public class FakeItem implements DisplayItem { public class FakeItem_17 extends DisplayItem {
private static Map<String, List<FakeItem>> fakes = new HashMap<String, List<FakeItem>>(); private static Map<String, List<FakeItem_17>> fakes = new HashMap<>();
private static boolean registered = false; private static boolean registered = false;
private static int lastId = Integer.MAX_VALUE; private static int lastId = Integer.MAX_VALUE;
@ -39,6 +40,13 @@ public class FakeItem implements DisplayItem {
private final int eid; private final int eid;
private boolean created = false; private boolean created = false;
public FakeItem_17(final ContainerShop containerShop, final ItemStack item) {
this.itemStack = item;
this.location = containerShop.getLocation().clone().add(0.5, 1, 0.5);
this.eid = getFakeEntityId();
create();
}
public static boolean isRegistered() { public static boolean isRegistered() {
return registered; return registered;
} }
@ -67,9 +75,9 @@ public class FakeItem implements DisplayItem {
final Player p = event.getPlayer(); final Player p = event.getPlayer();
final int chunkX = packet.getIntegers().read(0); final int chunkX = packet.getIntegers().read(0);
final int chunkZ = packet.getIntegers().read(1); final int chunkZ = packet.getIntegers().read(1);
final List<FakeItem> fakesInChunk = fakes.get(getChunkIdentifyString(p.getWorld().getChunkAt(chunkX, chunkZ))); final List<FakeItem_17> fakesInChunk = fakes.get(getChunkIdentifyString(p.getWorld().getChunkAt(chunkX, chunkZ)));
if (fakesInChunk != null) { if (fakesInChunk != null) {
for (final FakeItem fake : fakesInChunk) { for (final FakeItem_17 fake : fakesInChunk) {
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getSpawnPacket()); ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getSpawnPacket());
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getVelocityPacket()); ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getVelocityPacket());
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getMetadataPacket()); ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getMetadataPacket());
@ -88,9 +96,9 @@ public class FakeItem implements DisplayItem {
final int[] chunksX = packet.getIntegerArrays().read(0); final int[] chunksX = packet.getIntegerArrays().read(0);
final int[] chunksZ = packet.getIntegerArrays().read(1); final int[] chunksZ = packet.getIntegerArrays().read(1);
for (int i = 0; i < chunksX.length; i++) { for (int i = 0; i < chunksX.length; i++) {
final List<FakeItem> fakesInChunk = fakes.get(getChunkIdentifyString(p.getWorld().getChunkAt(chunksX[i], chunksZ[i]))); final List<FakeItem_17> fakesInChunk = fakes.get(getChunkIdentifyString(p.getWorld().getChunkAt(chunksX[i], chunksZ[i])));
if (fakesInChunk != null) { if (fakesInChunk != null) {
for (final FakeItem fake : fakesInChunk) { for (final FakeItem_17 fake : fakesInChunk) {
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getSpawnPacket()); ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getSpawnPacket());
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getVelocityPacket()); ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getVelocityPacket());
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getMetadataPacket()); ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getMetadataPacket());
@ -119,12 +127,6 @@ public class FakeItem implements DisplayItem {
return (int) Math.floor(value * 32.0D); return (int) Math.floor(value * 32.0D);
} }
public FakeItem(final ContainerShop containerShop, final ItemStack item) {
this.itemStack = item;
this.location = containerShop.getLocation().clone().add(0.5, 1, 0.5);
this.eid = getFakeEntityId();
}
@Override @Override
public Location getDisplayLocation() { public Location getDisplayLocation() {
return location; return location;
@ -170,9 +172,9 @@ public class FakeItem implements DisplayItem {
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getMetadataPacket()); ProtocolLibrary.getProtocolManager().broadcastServerPacket(getMetadataPacket());
final String chunkId = getChunkIdentifyString(location.getChunk()); final String chunkId = getChunkIdentifyString(location.getChunk());
List<FakeItem> fakesInChunk = fakes.get(chunkId); List<FakeItem_17> fakesInChunk = fakes.get(chunkId);
if (fakesInChunk == null) { if (fakesInChunk == null) {
fakesInChunk = new ArrayList<FakeItem>(); fakesInChunk = new ArrayList<>();
} }
fakesInChunk.add(this); fakesInChunk.add(this);
fakes.put(chunkId, fakesInChunk); fakes.put(chunkId, fakesInChunk);
@ -186,7 +188,7 @@ public class FakeItem implements DisplayItem {
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getDestoryPacket()); ProtocolLibrary.getProtocolManager().broadcastServerPacket(getDestoryPacket());
final String chunkId = getChunkIdentifyString(location.getChunk()); final String chunkId = getChunkIdentifyString(location.getChunk());
final List<FakeItem> fakesInChunk = fakes.get(chunkId); final List<FakeItem_17> fakesInChunk = fakes.get(chunkId);
if (fakesInChunk == null) { if (fakesInChunk == null) {
// NOTE: This is what should not happens if everything is correct. // NOTE: This is what should not happens if everything is correct.
created = false; created = false;
@ -207,7 +209,7 @@ public class FakeItem implements DisplayItem {
final PacketContainer fakePacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_METADATA); final PacketContainer fakePacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_METADATA);
fakePacket.getIntegers().write(0, eid); fakePacket.getIntegers().write(0, eid);
final WrappedWatchableObject itemMeta = new WrappedWatchableObject(10, itemStack); final WrappedWatchableObject itemMeta = new WrappedWatchableObject(10, itemStack);
final List<WrappedWatchableObject> entityMetaList = new ArrayList<WrappedWatchableObject>(1); final List<WrappedWatchableObject> entityMetaList = new ArrayList<>(1);
entityMetaList.add(itemMeta); entityMetaList.add(itemMeta);
fakePacket.getWatchableCollectionModifier().write(0, entityMetaList); fakePacket.getWatchableCollectionModifier().write(0, entityMetaList);
return fakePacket; return fakePacket;

View File

@ -0,0 +1,226 @@
package org.maxgamer.QuickShop.Shop.Item;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.maxgamer.QuickShop.Shop.ContainerShop;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer;
import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject;
import com.google.common.base.Optional;
/**
* Minecraft 虚拟悬浮物品工具类
* 需要depend ProtocolLib 4.x
*
* @author 橙子(chengzi)
* @version 1.1.0
*/
public class FakeItem_18_110 extends DisplayItem {
private static Map<String, List<FakeItem_18_110>> fakes = new HashMap<>();
private static boolean registered = false;
private static int lastId = Integer.MAX_VALUE;
private final ItemStack itemStack;
private final Location location;
private final int eid;
private final UUID uuid;
private boolean created = false;
public FakeItem_18_110(final ContainerShop containerShop, final ItemStack item) {
this.itemStack = item;
this.location = containerShop.getLocation().clone().add(0.5, 1, 0.5);
this.eid = getFakeEntityId();
this.uuid = UUID.randomUUID();
}
public static boolean isRegistered() {
return registered;
}
public static void register(final Plugin plugin) {
if (registered) {
return;
}
final PluginManager pm = Bukkit.getPluginManager();
final Plugin p = pm.getPlugin("ProtocolLib");
if (p != null) {
if (!p.isEnabled()) {
pm.enablePlugin(p);
}
if (!p.isEnabled()) {
throw new IllegalStateException("前置插件ProtocolLib启动失败 请检查版本.");
}
} else {
throw new IllegalStateException("服务器未找到前置插件ProtocolLib.");
}
final PacketAdapter chunkPacketListener = new PacketAdapter(plugin, PacketType.Play.Server.MAP_CHUNK) {
@Override
public void onPacketSending(final PacketEvent event) {
try {
final PacketContainer packet = event.getPacket();
final Player p = event.getPlayer();
final int chunkX = packet.getIntegers().read(0);
final int chunkZ = packet.getIntegers().read(1);
final List<FakeItem_18_110> fakesInChunk = fakes.get(getChunkIdentifyString(p.getWorld().getChunkAt(chunkX, chunkZ)));
if (fakesInChunk != null) {
for (final FakeItem_18_110 fake : fakesInChunk) {
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getSpawnPacket());
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getMetadataPacket());
}
}
} catch (final Exception e) {
}
}
};
final PacketAdapter chunkBulkPacketListener = new PacketAdapter(plugin, PacketType.Play.Server.MAP_CHUNK) {
@Override
public void onPacketSending(final PacketEvent event) {
try {
final PacketContainer packet = event.getPacket();
final Player p = event.getPlayer();
final int[] chunksX = packet.getIntegerArrays().read(0);
final int[] chunksZ = packet.getIntegerArrays().read(1);
for (int i = 0; i < chunksX.length; i++) {
final List<FakeItem_18_110> fakesInChunk = fakes.get(getChunkIdentifyString(p.getWorld().getChunkAt(chunksX[i], chunksZ[i])));
if (fakesInChunk != null) {
for (final FakeItem_18_110 fake : fakesInChunk) {
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getSpawnPacket());
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getMetadataPacket());
}
}
}
} catch (final Exception e) {
}
}
};
ProtocolLibrary.getProtocolManager().addPacketListener(chunkPacketListener);
ProtocolLibrary.getProtocolManager().addPacketListener(chunkBulkPacketListener);
registered = true;
}
private static String getChunkIdentifyString(final Chunk chunk) {
return chunk.getWorld().getName() + "@@" + chunk.getX() + "@@" + chunk.getZ();
}
private static int getFakeEntityId() {
return lastId--;
}
@Override
public Location getDisplayLocation() {
return location;
}
@Override
public Item getItem() {
return null;
}
@Override
public void remove() {
destory();
}
@Override
public boolean removeDupe() {
return true;
}
@Override
public void respawn() {
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getDestoryPacket());
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getSpawnPacket());
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getMetadataPacket());
}
@Override
public void spawn() {
create();
}
private void create() {
if (!registered) {
throw new IllegalStateException("You have to call the register method first.");
}
if (created) {
return;
}
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getSpawnPacket());
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getMetadataPacket());
final String chunkId = getChunkIdentifyString(location.getChunk());
List<FakeItem_18_110> fakesInChunk = fakes.get(chunkId);
if (fakesInChunk == null) {
fakesInChunk = new ArrayList<>();
}
fakesInChunk.add(this);
fakes.put(chunkId, fakesInChunk);
created = true;
}
private void destory() {
if (!created) {
return;
}
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getDestoryPacket());
final String chunkId = getChunkIdentifyString(location.getChunk());
final List<FakeItem_18_110> fakesInChunk = fakes.get(chunkId);
if (fakesInChunk == null) {
// NOTE: This is what should not happens if everything is correct.
created = false;
return;
}
fakesInChunk.remove(this);
fakes.put(chunkId, fakesInChunk);
created = false;
}
private PacketContainer getDestoryPacket() {
final PacketContainer fakePacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_DESTROY, true);
fakePacket.getIntegerArrays().write(0, new int[] { eid });
return fakePacket;
}
private PacketContainer getMetadataPacket() {
final PacketContainer fakePacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_METADATA);
fakePacket.getIntegers().write(0, eid);
final WrappedDataWatcher wr = new WrappedDataWatcher();
final Serializer serializer = WrappedDataWatcher.Registry.getItemStackSerializer(true);
final WrappedDataWatcherObject object = new WrappedDataWatcher.WrappedDataWatcherObject(6, serializer);
wr.setObject(object, Optional.of(itemStack));
fakePacket.getWatchableCollectionModifier().write(0, wr.getWatchableObjects());
return fakePacket;
}
private PacketContainer getSpawnPacket() {
final PacketContainer fakePacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.SPAWN_ENTITY);
fakePacket.getIntegers().write(0, eid);
fakePacket.getModifier().write(1, uuid);
fakePacket.getDoubles().write(0, location.getX());
fakePacket.getDoubles().write(1, location.getY());
fakePacket.getDoubles().write(2, location.getZ());
fakePacket.getIntegers().write(6, 2);
return fakePacket;
}
}

View File

@ -1,4 +1,4 @@
package org.maxgamer.QuickShop.Shop; package org.maxgamer.QuickShop.Shop.Item;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
@ -6,13 +6,14 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Item; import org.bukkit.entity.Item;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.maxgamer.QuickShop.Shop.Shop;
import org.maxgamer.QuickShop.Util.NMS; import org.maxgamer.QuickShop.Util.NMS;
/** /**
* @author Netherfoam A display item, that spawns a block above the chest and * @author Netherfoam A display item, that spawns a block above the chest and
* cannot be interacted with. * cannot be interacted with.
*/ */
public class NormalItem implements DisplayItem { public class NormalItem extends DisplayItem {
private final ItemStack iStack; private final ItemStack iStack;
private Item item; private Item item;
private final Shop shop; private final Shop shop;

View File

@ -24,13 +24,11 @@ import org.maxgamer.QuickShop.Database.Database;
import org.maxgamer.QuickShop.Util.MsgUtil; import org.maxgamer.QuickShop.Util.MsgUtil;
import org.maxgamer.QuickShop.Util.Util; import org.maxgamer.QuickShop.Util.Util;
import cn.citycraft.PluginHelper.kit.PluginKit;
public class ShopManager { public class ShopManager {
private final HashMap<String, Info> actions = new HashMap<String, Info>(); private final HashMap<String, Info> actions = new HashMap<>();
private final QuickShop plugin; private final QuickShop plugin;
private final HashMap<String, HashMap<ShopChunk, HashMap<Location, Shop>>> shops = new HashMap<String, HashMap<ShopChunk, HashMap<Location, Shop>>>(); private final HashMap<String, HashMap<ShopChunk, HashMap<Location, Shop>>> shops = new HashMap<>();
public ShopManager(final QuickShop plugin) { public ShopManager(final QuickShop plugin) {
this.plugin = plugin; this.plugin = plugin;
@ -226,6 +224,162 @@ public class ShopManager {
} }
/* Creation handling */ /* Creation handling */
if (info.getAction() == ShopAction.CREATE) { if (info.getAction() == ShopAction.CREATE) {
create(p, info, message);
} else if (/* Purchase Handling */info.getAction() == ShopAction.BUY) {
int amount = 0;
try {
amount = Integer.parseInt(message);
} catch (final NumberFormatException e) {
p.sendMessage(MsgUtil.p("shop-purchase-cancelled"));
return;
}
// Get the shop they interacted with
final Shop shop = plugin.getShopManager().getShop(info.getLocation());
// It's not valid anymore
if (shop == null || Util.canBeShop(info.getLocation().getBlock()) == false) {
p.sendMessage(MsgUtil.p("chest-was-removed"));
return;
}
if (info.hasChanged(shop)) {
p.sendMessage(MsgUtil.p("shop-has-changed"));
return;
}
if (shop.isSelling()) {
sale(p, shop, amount);
} else if (shop.isBuying()) {
buy(p, shop, amount);
}
shop.setSignText(); // Update the signs count
} else {
/* If it was already cancelled (from destroyed) */
return; // It was cancelled, go away.
}
}
/**
* Loads the given shop into storage. This method is used for loading data
* from the database. Do not use this method to create a shop.
*
* @param world
* The world the shop is in
* @param shop
* The shop to load
*/
public void loadShop(final String world, final Shop shop) {
this.addShop(world, shop);
}
/**
* Removes a shop from the world. Does NOT remove it from the database. *
* REQUIRES * the world to be loaded
*
* @param shop
* The shop to remove
*/
public void removeShop(final Shop shop) {
final Location loc = shop.getLocation();
final String world = loc.getWorld().getName();
final HashMap<ShopChunk, HashMap<Location, Shop>> inWorld = this.getShops().get(world);
final int x = (int) Math.floor((shop.getLocation().getBlockX()) / 16.0);
final int z = (int) Math.floor((shop.getLocation().getBlockZ()) / 16.0);
final ShopChunk shopChunk = new ShopChunk(world, x, z);
final HashMap<Location, Shop> inChunk = inWorld.get(shopChunk);
inChunk.remove(loc);
}
/**
* Adds a shop to the world. Does NOT require the chunk or world to be
* loaded
*
* @param world
* The name of the world
* @param shop
* The shop to add
*/
private void addShop(final String world, final Shop shop) {
HashMap<ShopChunk, HashMap<Location, Shop>> inWorld = this.getShops().get(world);
// There's no world storage yet. We need to create that hashmap.
if (inWorld == null) {
inWorld = new HashMap<>(3);
// Put it in the data universe
this.getShops().put(world, inWorld);
}
// Calculate the chunks coordinates. These are 1,2,3 for each chunk, NOT
// location rounded to the nearest 16.
final int x = (int) Math.floor((shop.getLocation().getBlockX()) / 16.0);
final int z = (int) Math.floor((shop.getLocation().getBlockZ()) / 16.0);
// Get the chunk set from the world info
final ShopChunk shopChunk = new ShopChunk(world, x, z);
HashMap<Location, Shop> inChunk = inWorld.get(shopChunk);
// That chunk data hasn't been created yet - Create it!
if (inChunk == null) {
inChunk = new HashMap<>(1);
// Put it in the world
inWorld.put(shopChunk, inChunk);
}
// Put the shop in its location in the chunk list.
inChunk.put(shop.getLocation(), shop);
}
private void buy(final Player p, final Shop shop, final int amount) {
final int space = shop.getRemainingSpace();
if (space < amount) {
p.sendMessage(MsgUtil.p("shop-has-no-space", "" + space, shop.getDataName()));
return;
}
final int count = Util.countItems(p.getInventory(), shop.getItem());
// Not enough items
if (amount > count) {
p.sendMessage(MsgUtil.p("you-dont-have-that-many-items", "" + count, shop.getDataName()));
return;
}
if (amount == 0) {
// Dumb.
MsgUtil.sendPurchaseSuccess(p, shop, amount);
return;
} else if (amount < 0) {
// & Dumber
p.sendMessage(MsgUtil.p("negative-amount"));
return;
}
// Money handling
if (!p.getName().equals(shop.getOwner())) {
// Don't tax them if they're purchasing from
// themselves.
// Do charge an amount of tax though.
final double tax = plugin.getConfigManager().getTax();
final double total = amount * shop.getPrice();
if (!shop.isUnlimited() || plugin.getConfig().getBoolean("shop.pay-unlimited-shop-owners")) {
// Tries to check their balance nicely to see if
// they can afford it.
if (plugin.getEcon().getBalance(shop.getOwner()) < amount * shop.getPrice()) {
p.sendMessage(MsgUtil.p("the-owner-cant-afford-to-buy-from-you", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(shop.getOwner()))));
return;
}
// Check for plugins faking econ.has(amount)
if (!plugin.getEcon().withdraw(shop.getOwner(), total)) {
p.sendMessage(MsgUtil.p("the-owner-cant-afford-to-buy-from-you", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(shop.getOwner()))));
return;
}
if (tax != 0) {
plugin.getEcon().deposit(plugin.getConfigManager().getTaxAccount(), total * tax);
}
}
// Give them the money after we know we succeeded
plugin.getEcon().deposit(p.getName(), total * (1 - tax));
// Notify the owner of the purchase.
String msg = MsgUtil.p("player-sold-to-your-store", p.getName(), "" + amount, shop.getDataName());
if (space == amount) {
msg += "\n" + MsgUtil.p("shop-out-of-space", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ());
}
MsgUtil.send(shop.getOwner(), msg);
}
shop.buy(p, amount);
MsgUtil.sendSellSuccess(p, shop, amount);
plugin.log(String.format("玩家: %s 出售了 %s 件商品 到 %s 获得 %s", p.getName(), amount, shop.toString(), shop.getPrice() * amount));
}
private void create(final Player p, final Info info, final String message) {
try { try {
// Checking the shop can be created // Checking the shop can be created
if (plugin.getShopManager().getShop(info.getLocation()) != null) { if (plugin.getShopManager().getShop(info.getLocation()) != null) {
@ -298,7 +452,7 @@ public class ShopManager {
bs.setType(Material.WALL_SIGN); bs.setType(Material.WALL_SIGN);
final Sign sign = (Sign) bs.getData(); final Sign sign = (Sign) bs.getData();
sign.setFacingDirection(bf); sign.setFacingDirection(bf);
PluginKit.runTask(new Runnable() { Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override @Override
public void run() { public void run() {
bs.update(true); bs.update(true);
@ -324,29 +478,8 @@ public class ShopManager {
return; return;
} }
} }
/* Purchase Handling */
else if (info.getAction() == ShopAction.BUY)
{ private void sale(final Player p, final Shop shop, final int amount) {
int amount = 0;
try {
amount = Integer.parseInt(message);
} catch (final NumberFormatException e) {
p.sendMessage(MsgUtil.p("shop-purchase-cancelled"));
return;
}
// Get the shop they interacted with
final Shop shop = plugin.getShopManager().getShop(info.getLocation());
// It's not valid anymore
if (shop == null || Util.canBeShop(info.getLocation().getBlock()) == false) {
p.sendMessage(MsgUtil.p("chest-was-removed"));
return;
}
if (info.hasChanged(shop)) {
p.sendMessage(MsgUtil.p("shop-has-changed"));
return;
}
if (shop.isSelling()) {
final int stock = shop.getRemainingStock(); final int stock = shop.getRemainingStock();
if (stock < amount) { if (stock < amount) {
p.sendMessage(MsgUtil.p("shop-stock-too-low", "" + shop.getRemainingStock(), shop.getDataName())); p.sendMessage(MsgUtil.p("shop-stock-too-low", "" + shop.getRemainingStock(), shop.getDataName()));
@ -398,15 +531,13 @@ public class ShopManager {
if (plugin.getConfigManager().isShowTax()) { if (plugin.getConfigManager().isShowTax()) {
String msg = MsgUtil.p("player-bought-from-your-store-tax", p.getName(), "" + amount, shop.getDataName(), Util.format((tax * total))); String msg = MsgUtil.p("player-bought-from-your-store-tax", p.getName(), "" + amount, shop.getDataName(), Util.format((tax * total)));
if (stock == amount) { if (stock == amount) {
msg += "\n" msg += "\n" + MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), shop.getDataName());
+ MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), shop.getDataName());
} }
MsgUtil.send(shop.getOwner(), msg); MsgUtil.send(shop.getOwner(), msg);
} else { } else {
String msg = MsgUtil.p("player-bought-from-your-store", p.getName(), "" + amount, shop.getDataName()); String msg = MsgUtil.p("player-bought-from-your-store", p.getName(), "" + amount, shop.getDataName());
if (stock == amount) { if (stock == amount) {
msg += "\n" msg += "\n" + MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), shop.getDataName());
+ MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), shop.getDataName());
} }
MsgUtil.send(shop.getOwner(), msg); MsgUtil.send(shop.getOwner(), msg);
} }
@ -415,137 +546,6 @@ public class ShopManager {
shop.sell(p, amount); shop.sell(p, amount);
MsgUtil.sendPurchaseSuccess(p, shop, amount); MsgUtil.sendPurchaseSuccess(p, shop, amount);
plugin.log(String.format("玩家: %s 从 %s 购买了 %s 件商品 花费 %s", p.getName(), shop.toString(), amount, shop.getPrice() * amount)); plugin.log(String.format("玩家: %s 从 %s 购买了 %s 件商品 花费 %s", p.getName(), shop.toString(), amount, shop.getPrice() * amount));
} else if (shop.isBuying()) {
final int space = shop.getRemainingSpace();
if (space < amount) {
p.sendMessage(MsgUtil.p("shop-has-no-space", "" + space, shop.getDataName()));
return;
}
final int count = Util.countItems(p.getInventory(), shop.getItem());
// Not enough items
if (amount > count) {
p.sendMessage(MsgUtil.p("you-dont-have-that-many-items", "" + count, shop.getDataName()));
return;
}
if (amount == 0) {
// Dumb.
MsgUtil.sendPurchaseSuccess(p, shop, amount);
return;
} else if (amount < 0) {
// & Dumber
p.sendMessage(MsgUtil.p("negative-amount"));
return;
}
// Money handling
if (!p.getName().equals(shop.getOwner())) {
// Don't tax them if they're purchasing from
// themselves.
// Do charge an amount of tax though.
final double tax = plugin.getConfigManager().getTax();
final double total = amount * shop.getPrice();
if (!shop.isUnlimited() || plugin.getConfig().getBoolean("shop.pay-unlimited-shop-owners")) {
// Tries to check their balance nicely to see if
// they can afford it.
if (plugin.getEcon().getBalance(shop.getOwner()) < amount * shop.getPrice()) {
p.sendMessage(MsgUtil.p("the-owner-cant-afford-to-buy-from-you", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(shop.getOwner()))));
return;
}
// Check for plugins faking econ.has(amount)
if (!plugin.getEcon().withdraw(shop.getOwner(), total)) {
p.sendMessage(MsgUtil.p("the-owner-cant-afford-to-buy-from-you", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(shop.getOwner()))));
return;
}
if (tax != 0) {
plugin.getEcon().deposit(plugin.getConfigManager().getTaxAccount(), total * tax);
}
}
// Give them the money after we know we succeeded
plugin.getEcon().deposit(p.getName(), total * (1 - tax));
// Notify the owner of the purchase.
String msg = MsgUtil.p("player-sold-to-your-store", p.getName(), "" + amount, shop.getDataName());
if (space == amount) {
msg += "\n" + MsgUtil.p("shop-out-of-space", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ());
}
MsgUtil.send(shop.getOwner(), msg);
}
shop.buy(p, amount);
MsgUtil.sendSellSuccess(p, shop, amount);
plugin.log(String.format("玩家: %s 出售了 %s 件商品 到 %s 获得 %s", p.getName(), amount, shop.toString(), shop.getPrice() * amount));
}
shop.setSignText(); // Update the signs count
}
/* If it was already cancelled (from destroyed) */
else
{
return; // It was cancelled, go away.
}
}
/**
* Loads the given shop into storage. This method is used for loading data
* from the database. Do not use this method to create a shop.
*
* @param world
* The world the shop is in
* @param shop
* The shop to load
*/
public void loadShop(final String world, final Shop shop) {
this.addShop(world, shop);
}
/**
* Removes a shop from the world. Does NOT remove it from the database. *
* REQUIRES * the world to be loaded
*
* @param shop
* The shop to remove
*/
public void removeShop(final Shop shop) {
final Location loc = shop.getLocation();
final String world = loc.getWorld().getName();
final HashMap<ShopChunk, HashMap<Location, Shop>> inWorld = this.getShops().get(world);
final int x = (int) Math.floor((shop.getLocation().getBlockX()) / 16.0);
final int z = (int) Math.floor((shop.getLocation().getBlockZ()) / 16.0);
final ShopChunk shopChunk = new ShopChunk(world, x, z);
final HashMap<Location, Shop> inChunk = inWorld.get(shopChunk);
inChunk.remove(loc);
}
/**
* Adds a shop to the world. Does NOT require the chunk or world to be
* loaded
*
* @param world
* The name of the world
* @param shop
* The shop to add
*/
private void addShop(final String world, final Shop shop) {
HashMap<ShopChunk, HashMap<Location, Shop>> inWorld = this.getShops().get(world);
// There's no world storage yet. We need to create that hashmap.
if (inWorld == null) {
inWorld = new HashMap<ShopChunk, HashMap<Location, Shop>>(3);
// Put it in the data universe
this.getShops().put(world, inWorld);
}
// Calculate the chunks coordinates. These are 1,2,3 for each chunk, NOT
// location rounded to the nearest 16.
final int x = (int) Math.floor((shop.getLocation().getBlockX()) / 16.0);
final int z = (int) Math.floor((shop.getLocation().getBlockZ()) / 16.0);
// Get the chunk set from the world info
final ShopChunk shopChunk = new ShopChunk(world, x, z);
HashMap<Location, Shop> inChunk = inWorld.get(shopChunk);
// That chunk data hasn't been created yet - Create it!
if (inChunk == null) {
inChunk = new HashMap<Location, Shop>(1);
// Put it in the world
inWorld.put(shopChunk, inChunk);
}
// Put the shop in its location in the chunk list.
inChunk.put(shop.getLocation(), shop);
} }
public class ShopIterator implements Iterator<Shop> { public class ShopIterator implements Iterator<Shop> {

View File

@ -13,12 +13,12 @@ import org.bukkit.inventory.ItemStack;
import org.maxgamer.QuickShop.QuickShop; import org.maxgamer.QuickShop.QuickShop;
import org.maxgamer.QuickShop.Shop.Shop; import org.maxgamer.QuickShop.Shop.Shop;
import cn.citycraft.PluginHelper.config.FileConfig; import pw.yumc.YumCore.config.FileConfig;
import cn.citycraft.PluginHelper.tellraw.FancyMessage; import pw.yumc.YumCore.tellraw.Tellraw;
public class MsgUtil { public class MsgUtil {
private static FileConfig messages; private static FileConfig messages;
private static HashMap<String, LinkedList<String>> player_messages = new HashMap<String, LinkedList<String>>(); private static HashMap<String, LinkedList<String>> player_messages = new HashMap<>();
private static QuickShop plugin; private static QuickShop plugin;
/** /**
@ -58,7 +58,7 @@ public class MsgUtil {
public static void init(final QuickShop plugin) { public static void init(final QuickShop plugin) {
MsgUtil.plugin = plugin; MsgUtil.plugin = plugin;
// Load messages.yml // Load messages.yml
messages = new FileConfig(plugin, "messages.yml"); messages = new FileConfig("messages.yml");
// Parse colour codes // Parse colour codes
Util.parseColours(messages); Util.parseColours(messages);
} }
@ -75,7 +75,7 @@ public class MsgUtil {
final String message = rs.getString("message"); final String message = rs.getString("message");
LinkedList<String> msgs = player_messages.get(owner); LinkedList<String> msgs = player_messages.get(owner);
if (msgs == null) { if (msgs == null) {
msgs = new LinkedList<String>(); msgs = new LinkedList<>();
player_messages.put(owner, msgs); player_messages.put(owner, msgs);
} }
msgs.add(message); msgs.add(message);
@ -122,7 +122,7 @@ public class MsgUtil {
if (p == null || !p.isOnline()) { if (p == null || !p.isOnline()) {
LinkedList<String> msgs = player_messages.get(player); LinkedList<String> msgs = player_messages.get(player);
if (msgs == null) { if (msgs == null) {
msgs = new LinkedList<String>(); msgs = new LinkedList<>();
player_messages.put(player, msgs); player_messages.put(player, msgs);
} }
msgs.add(message); msgs.add(message);
@ -137,8 +137,8 @@ public class MsgUtil {
public static void sendItemMessage(final Player p, final ItemStack is, final String msg) { public static void sendItemMessage(final Player p, final ItemStack is, final String msg) {
try { try {
final FancyMessage fm = FancyMessage.newFM(); final Tellraw fm = Tellraw.create();
fm.text(msg).itemTooltip(is).send(p); fm.text(msg).item(is).send(p);
} catch (Exception | NoClassDefFoundError | NoSuchMethodError e) { } catch (Exception | NoClassDefFoundError | NoSuchMethodError e) {
plugin.getConfigManager().setEnableMagicLib(false); plugin.getConfigManager().setEnableMagicLib(false);
p.sendMessage(msg); p.sendMessage(msg);
@ -188,7 +188,8 @@ public class MsgUtil {
p.sendMessage(ChatColor.DARK_PURPLE + "| " + MsgUtil.p("menu.shop-information")); p.sendMessage(ChatColor.DARK_PURPLE + "| " + MsgUtil.p("menu.shop-information"));
p.sendMessage(ChatColor.DARK_PURPLE p.sendMessage(ChatColor.DARK_PURPLE
+ "| " + "| "
+ MsgUtil.p("menu.owner", Bukkit.getOfflinePlayer(shop.getOwner()).getName() == null ? (shop.isUnlimited() ? "系统商店" : "未知") : Bukkit.getOfflinePlayer(shop.getOwner()).getName())); + MsgUtil.p("menu.owner",
Bukkit.getOfflinePlayer(shop.getOwner()).getName() == null ? (shop.isUnlimited() ? "系统商店" : "未知") : Bukkit.getOfflinePlayer(shop.getOwner()).getName()));
final String msg = ChatColor.DARK_PURPLE + "| " + MsgUtil.p("menu.item", shop.getDataName()); final String msg = ChatColor.DARK_PURPLE + "| " + MsgUtil.p("menu.item", shop.getDataName());
sendItemMessage(p, shop.getItem(), msg); sendItemMessage(p, shop.getItem(), msg);
if (Util.isTool(item.getType())) { if (Util.isTool(item.getType())) {

View File

@ -23,16 +23,16 @@ import org.bukkit.material.MaterialData;
import org.bukkit.material.Sign; import org.bukkit.material.Sign;
import org.maxgamer.QuickShop.QuickShop; import org.maxgamer.QuickShop.QuickShop;
import cn.citycraft.PluginHelper.utils.LocalUtil; import pw.yumc.YumCore.misc.L10N;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class Util { public class Util {
private static HashSet<Material> blacklist = new HashSet<Material>(); private static HashSet<Material> blacklist = new HashSet<>();
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##"); private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##");
private static QuickShop plugin; private static QuickShop plugin;
private static HashSet<Material> shoppables = new HashSet<Material>(); private static HashSet<Material> shoppables = new HashSet<>();
private static HashSet<Material> tools = new HashSet<Material>(); private static HashSet<Material> tools = new HashSet<>();
private static HashSet<Material> transparent = new HashSet<Material>(); private static HashSet<Material> transparent = new HashSet<>();
public static void addTransparentBlock(final Material m) { public static void addTransparentBlock(final Material m) {
if (transparent.add(m) == false) { if (transparent.add(m) == false) {
@ -162,7 +162,7 @@ public class Util {
* @return The human readable item name. * @return The human readable item name.
*/ */
public static String getName(final ItemStack i) { public static String getName(final ItemStack i) {
final String vanillaName = LocalUtil.getItemFullName(i); final String vanillaName = L10N.getItemFullName(i);
return vanillaName; return vanillaName;
} }