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

View File

@ -24,30 +24,32 @@ import org.maxgamer.QuickShop.Shop.ShopChunk;
import org.maxgamer.QuickShop.Shop.ShopType;
import org.maxgamer.QuickShop.Util.MsgUtil;
import cn.citycraft.PluginHelper.commands.HandlerCommand;
import cn.citycraft.PluginHelper.commands.HandlerCommands;
import cn.citycraft.PluginHelper.commands.HandlerDescription;
import cn.citycraft.PluginHelper.commands.InvokeCommandEvent;
import cn.citycraft.PluginHelper.commands.InvokeSubCommand;
import cn.citycraft.PluginHelper.utils.StringUtil;
import pw.yumc.YumCore.bukkit.P;
import pw.yumc.YumCore.commands.CommandArgument;
import pw.yumc.YumCore.commands.CommandExecutor;
import pw.yumc.YumCore.commands.CommandHelpParse;
import pw.yumc.YumCore.commands.CommandManager;
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 {
QuickShop plugin;
public class QuickShopCommands implements CommandExecutor, CommandHelpParse {
QuickShop plugin = P.getPlugin();
public QuickShopCommands(final QuickShop plugin) {
this.plugin = plugin;
final InvokeSubCommand ics = new InvokeSubCommand(plugin, "qs");
ics.registerCommands(this);
ics.setHandlerDescription(this);
public QuickShopCommands() {
new CommandManager("qs", this).setHelpParse(this);
}
@HandlerCommand(name = "buy", aliases = { "b" }, permission = "quickshop.create.buy", onlyPlayerExecutable = true, description = "command.description.buy")
public void buy(final InvokeCommandEvent e) {
@Cmd(aliases = "b", permission = "quickshop.create.buy", executor = Executor.PLAYER)
@Help("command.description.buy")
public void buy(final CommandArgument e) {
changeShopType(e.getSender(), ShopType.BUYING);
}
@HandlerCommand(name = "clean", aliases = "c", permission = "quickshop.clean", description = "command.description.clean")
public void clean(final InvokeCommandEvent e) {
@Cmd(aliases = "c", permission = "quickshop.clean")
@Help("command.description.clean")
public void clean(final CommandArgument e) {
final CommandSender sender = e.getSender();
sender.sendMessage(MsgUtil.p("command.cleaning"));
final Iterator<Shop> shIt = plugin.getShopManager().getShopIterator();
@ -71,8 +73,9 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
sender.sendMessage(MsgUtil.p("command.cleaned", "" + i));
}
@HandlerCommand(name = "empty", aliases = "e", permission = "quickshop.empty", description = "command.description.empty")
public void empty(final InvokeCommandEvent e) {
@Cmd(aliases = "e", permission = "quickshop.empty")
@Help("command.description.empty")
public void empty(final CommandArgument e) {
final CommandSender sender = e.getSender();
final BlockIterator bIt = new BlockIterator((Player) sender, 10);
while (bIt.hasNext()) {
@ -93,8 +96,9 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
return;
}
@HandlerCommand(name = "export", minimumArguments = 1, possibleArguments = "[mysql|sqlite]", permission = "quickshop.export", description = "command.description.export")
public void export(final InvokeCommandEvent e) {
@Cmd(minimumArguments = 1, permission = "quickshop.export")
@Help(value = "command.description.export", possibleArguments = "[mysql|sqlite]")
public void export(final CommandArgument e) {
final CommandSender sender = e.getSender();
final String type = e.getArgs()[0].toLowerCase();
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")
public void find(final InvokeCommandEvent e) {
@Cmd(aliases = "f", minimumArguments = 2, permission = "quickshop.find", executor = Executor.PLAYER)
@Help("command.description.find")
public void find(final CommandArgument e) {
final CommandSender sender = e.getSender();
String lookFor = StringUtil.consolidateStrings(e.getArgs(), 0);
String lookFor = StrKit.consolidateStrings(e.getArgs(), 0);
lookFor = lookFor.toLowerCase();
final Player p = (Player) sender;
final Location loc = p.getEyeLocation().clone();
@ -182,13 +187,9 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
return;
}
@Override
public String handler(final String arg0) {
return MsgUtil.p(arg0);
}
@HandlerCommand(name = "info", aliases = "i", permission = "quickshop.info", description = "command.description.info")
public void info(final InvokeCommandEvent e) {
@Cmd(aliases = "i", permission = "quickshop.info")
@Help("command.description.info")
public void info(final CommandArgument e) {
final CommandSender sender = e.getSender();
int buying, selling, doubles, chunks, worlds, unlimited;
buying = selling = doubles = chunks = worlds = unlimited = 0;
@ -223,8 +224,14 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
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")
public void price(final InvokeCommandEvent e) {
@Override
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 Player p = (Player) sender;
double price;
@ -294,8 +301,9 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
return;
}
@HandlerCommand(name = "refill", minimumArguments = 1, possibleArguments = "<数量>", permission = "quickshop.refill", description = "command.description.refill")
public void refill(final InvokeCommandEvent e) {
@Cmd(minimumArguments = 1, permission = "quickshop.refill", executor = Executor.PLAYER)
@Help(value = "command.description.refill", possibleArguments = "<数量>")
public void refill(final CommandArgument e) {
final CommandSender sender = e.getSender();
int add;
try {
@ -318,18 +326,19 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
return;
}
@HandlerCommand(name = "reload", permission = "quickshop.reload", description = "command.description.reload")
public void reload(final InvokeCommandEvent e) {
@Cmd(permission = "quickshop.reload")
@Help("command.description.reload")
public void reload(final CommandArgument e) {
final CommandSender sender = e.getSender();
sender.sendMessage(MsgUtil.p("command.reloading"));
plugin.reloadConfig();
Bukkit.getPluginManager().disablePlugin(plugin);
Bukkit.getPluginManager().enablePlugin(plugin);
return;
}
@HandlerCommand(name = "remove", aliases = "r", onlyPlayerExecutable = true, permission = "quickshop.delete", description = "command.description.remove")
public void remove(final InvokeCommandEvent e) {
@Cmd(aliases = "r", permission = "quickshop.delete", executor = Executor.PLAYER)
@Help("command.description.remove")
public void remove(final CommandArgument e) {
final Player p = (Player) e.getSender();
final BlockIterator bIt = new BlockIterator(p, 10);
while (bIt.hasNext()) {
@ -348,13 +357,15 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
p.sendMessage(ChatColor.RED + "未找到商店!");
}
@HandlerCommand(name = "sell", aliases = { "s" }, permission = "quickshop.create.sell", onlyPlayerExecutable = true, description = "command.description.sell")
public void sell(final InvokeCommandEvent e) {
@Cmd(aliases = "s", permission = "quickshop.create.sell")
@Help("command.description.sell")
public void sell(final CommandArgument e) {
changeShopType(e.getSender(), ShopType.SELLING);
}
@HandlerCommand(name = "setowner", aliases = "so", onlyPlayerExecutable = true, minimumArguments = 1, permission = "quickshop.setowner", description = "command.description.setowner")
public void setowner(final InvokeCommandEvent e) {
@Cmd(aliases = "so", minimumArguments = 1, permission = "quickshop.setowner", executor = Executor.PLAYER)
@Help("command.description.setowner")
public void setowner(final CommandArgument e) {
final CommandSender sender = e.getSender();
final String owner = e.getArgs()[0];
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"));
return;
}
@HandlerCommand(name = "unlimited", onlyPlayerExecutable = true, permission = "quickshop.unlimited", description = "command.description.unlimited")
public void unlimited(final InvokeCommandEvent e) {
@Cmd(permission = "quickshop.unlimited", executor = Executor.PLAYER)
@Help("command.description.unlimited")
public void unlimited(final CommandArgument e) {
final CommandSender sender = e.getSender();
final BlockIterator bIt = new BlockIterator((Player) sender, 10);
while (bIt.hasNext()) {
@ -387,7 +398,6 @@ public class QuickShopCommands implements HandlerCommands, HandlerDescription {
}
}
sender.sendMessage(MsgUtil.p("not-looking-at-shop"));
return;
}
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.inventory.ItemStack;
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 cn.citycraft.PluginHelper.tellraw.FancyMessage;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.config.FileConfig;
import pw.yumc.YumCore.tellraw.Tellraw;
public class ConfigManager {
private boolean enableMagicLib = false;
@ -88,23 +90,31 @@ public class ConfigManager {
if (config.getBoolean("fakeitem", true)) {
try {
plugin.getLogger().info("启用虚拟悬浮物 尝试启动中...");
FakeItem.register(plugin);
plugin.getLogger().info("虚拟悬浮物功能测试正常...");
FakeItem_18_110.register(plugin);
plugin.getLogger().info("虚拟悬浮物功能测试正常(1.8-1.10.2)...");
fakeItem = true;
} catch (final Error | Exception e) {
plugin.getLogger().warning("+=========================================");
plugin.getLogger().warning("| 警告: 启动虚拟物品失败 使用原版悬浮物品...");
plugin.getLogger().warning("+=========================================");
} 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("+=========================================");
Log.debug(e2);
}
}
}
if (config.getBoolean("usemagiclib", true)) {
try {
plugin.getLogger().info("启用魔改库 尝试启动中...");
final FancyMessage fm = FancyMessage.newFM("test");
fm.then("item").itemTooltip(new ItemStack(Material.DIAMOND_SWORD));
fm.then("link").link("ci.citycraft.cn");
final Tellraw fm = Tellraw.create("test");
fm.then("item").item(new ItemStack(Material.DIAMOND_SWORD));
fm.then("link").link("yumc.pw");
fm.then("suggest").suggest("qs help");
fm.toJSONString();
fm.toJsonString();
plugin.getLogger().info("魔改库功能测试正常...");
this.enableMagicLib = true;
} catch (final Error | Exception e) {

View File

@ -8,12 +8,12 @@ import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.Map.Entry;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
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.LogWatcher;
import cn.citycraft.PluginHelper.config.FileConfig;
import cn.citycraft.PluginHelper.utils.LocalUtil;
import cn.citycraft.PluginHelper.utils.VersionChecker;
import pw.yumc.YumCore.config.FileConfig;
import pw.yumc.YumCore.misc.L10N;
import pw.yumc.YumCore.update.SubscribeTask;
public class QuickShop extends JavaPlugin {
/** 初始化 QuickShop 的接口 */
@ -151,33 +151,6 @@ public class QuickShop extends JavaPlugin {
}
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 unload = 0;
@ -289,7 +262,6 @@ public class QuickShop extends JavaPlugin {
return;
}
configManager = new ConfigManager(this);
LocalUtil.init(this);
// Initialize Util
Util.initialize();
// Create the shop manager.
@ -359,26 +331,27 @@ public class QuickShop extends JavaPlugin {
}
// Command handlers
new QuickShopCommands(this);
new QuickShopCommands();
if (configManager.getFindDistance() > 100) {
getLogger().warning("商店查找半径过大 可能导致服务器Lag! 推荐使用低于 100 的配置!");
}
this.getLogger().info("载入完成! 版本: " + this.getDescription().getVersion() + " 重制 by 喵♂呜");
new VersionChecker(this);
new SubscribeTask();
}
@Override
public void onLoad() {
instance = this;
config = new FileConfig(this);
config = new FileConfig();
MsgUtil.init(this);
L10N.getItemName(new ItemStack(Material.AIR));
}
/** Reloads QuickShops config */
@Override
public void reloadConfig() {
config.reload();
LocalUtil.reload(this);
L10N.reload();
}
}

View File

@ -5,6 +5,7 @@ import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -17,11 +18,13 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
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.Util;
import cn.citycraft.PluginHelper.kit.P;
import cn.citycraft.PluginHelper.kit.PluginKit;
import pw.yumc.YumCore.bukkit.P;
public class ContainerShop implements Shop {
private final QuickShop plugin = (QuickShop) P.instance;
@ -53,13 +56,7 @@ public class ContainerShop implements Shop {
this.owner = owner;
this.item = item.clone();
this.item.setAmount(1);
if (plugin.getConfigManager().isDisplay()) {
if (plugin.getConfigManager().isFakeItem()) {
this.displayItem = new FakeItem(this, this.getItem());
} else {
this.displayItem = new NormalItem(this, this.getItem());
}
}
this.displayItem = DisplayItem.create(this);
this.shopType = ShopType.SELLING;
}
@ -360,7 +357,7 @@ public class ContainerShop implements Shop {
*/
@Override
public List<Sign> getSigns() {
final ArrayList<Sign> signs = new ArrayList<Sign>(1);
final ArrayList<Sign> signs = new ArrayList<>(1);
if (this.getLocation().getWorld() == null) {
return signs;
}
@ -518,7 +515,7 @@ public class ContainerShop implements Shop {
this.buy(p, -amount);
}
// 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();
if (this.isUnlimited()) {
final ItemStack item = this.item.clone();
@ -604,7 +601,7 @@ public class ContainerShop implements Shop {
}
final ContainerShop shop = this;
// 1.9不能异步修改木牌
PluginKit.runTask(new Runnable() {
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
final String[] lines = new String[4];
@ -637,7 +634,7 @@ public class ContainerShop implements Shop {
}
final List<Sign> signs = this.getSigns();
// 1.9不能异步修改木牌
PluginKit.runTask(new Runnable() {
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
for (final Sign sign : signs) {
@ -657,7 +654,15 @@ public class ContainerShop implements Shop {
@Override
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());
if (isUnlimited()) {
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());
if (trans && this.getDisplayItem() == null) {
if (plugin.getConfigManager().isFakeItem()) {
this.displayItem = new FakeItem(this, this.getItem());
this.displayItem = new FakeItem_17(this, this.getItem());
} else {
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.HashMap;
@ -13,6 +13,7 @@ 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;
@ -28,9 +29,9 @@ import com.comphenix.protocol.wrappers.WrappedWatchableObject;
* @author 橙子(chengzi)
* @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 int lastId = Integer.MAX_VALUE;
@ -39,6 +40,13 @@ public class FakeItem implements DisplayItem {
private final int eid;
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() {
return registered;
}
@ -67,9 +75,9 @@ public class FakeItem implements DisplayItem {
final Player p = event.getPlayer();
final int chunkX = packet.getIntegers().read(0);
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) {
for (final FakeItem fake : fakesInChunk) {
for (final FakeItem_17 fake : fakesInChunk) {
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getSpawnPacket());
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getVelocityPacket());
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getMetadataPacket());
@ -88,9 +96,9 @@ public class FakeItem implements DisplayItem {
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> 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) {
for (final FakeItem fake : fakesInChunk) {
for (final FakeItem_17 fake : fakesInChunk) {
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getSpawnPacket());
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getVelocityPacket());
ProtocolLibrary.getProtocolManager().sendServerPacket(p, fake.getMetadataPacket());
@ -119,12 +127,6 @@ public class FakeItem implements DisplayItem {
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
public Location getDisplayLocation() {
return location;
@ -170,9 +172,9 @@ public class FakeItem implements DisplayItem {
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getMetadataPacket());
final String chunkId = getChunkIdentifyString(location.getChunk());
List<FakeItem> fakesInChunk = fakes.get(chunkId);
List<FakeItem_17> fakesInChunk = fakes.get(chunkId);
if (fakesInChunk == null) {
fakesInChunk = new ArrayList<FakeItem>();
fakesInChunk = new ArrayList<>();
}
fakesInChunk.add(this);
fakes.put(chunkId, fakesInChunk);
@ -186,7 +188,7 @@ public class FakeItem implements DisplayItem {
ProtocolLibrary.getProtocolManager().broadcastServerPacket(getDestoryPacket());
final String chunkId = getChunkIdentifyString(location.getChunk());
final List<FakeItem> fakesInChunk = fakes.get(chunkId);
final List<FakeItem_17> fakesInChunk = fakes.get(chunkId);
if (fakesInChunk == null) {
// NOTE: This is what should not happens if everything is correct.
created = false;
@ -207,7 +209,7 @@ public class FakeItem implements DisplayItem {
final PacketContainer fakePacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_METADATA);
fakePacket.getIntegers().write(0, eid);
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);
fakePacket.getWatchableCollectionModifier().write(0, entityMetaList);
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.Location;
@ -6,13 +6,14 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import org.maxgamer.QuickShop.Shop.Shop;
import org.maxgamer.QuickShop.Util.NMS;
/**
* @author Netherfoam A display item, that spawns a block above the chest and
* cannot be interacted with.
*/
public class NormalItem implements DisplayItem {
public class NormalItem extends DisplayItem {
private final ItemStack iStack;
private Item item;
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.Util;
import cn.citycraft.PluginHelper.kit.PluginKit;
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 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) {
this.plugin = plugin;
@ -226,108 +224,8 @@ public class ShopManager {
}
/* Creation handling */
if (info.getAction() == ShopAction.CREATE) {
try {
// Checking the shop can be created
if (plugin.getShopManager().getShop(info.getLocation()) != null) {
p.sendMessage(MsgUtil.p("shop-already-owned"));
return;
}
if (Util.getSecondHalf(info.getLocation().getBlock()) != null && !p.hasPermission("quickshop.create.double")) {
p.sendMessage(MsgUtil.p("no-double-chests"));
return;
}
if (Util.canBeShop(info.getLocation().getBlock()) == false) {
p.sendMessage(MsgUtil.p("chest-was-removed"));
return;
}
// Price per item
double price;
if (plugin.getConfig().getBoolean("whole-number-prices-only")) {
price = Integer.parseInt(message);
} else {
price = Double.parseDouble(message);
}
if (price < 0.01) {
p.sendMessage(MsgUtil.p("price-too-cheap"));
return;
}
final double tax = plugin.getConfig().getDouble("shop.cost");
// Tax refers to the cost to create a shop. Not actual
// tax, that would be silly
if (tax != 0 && plugin.getEcon().getBalance(p.getName()) < tax) {
p.sendMessage(MsgUtil.p("you-cant-afford-a-new-shop", format(tax)));
return;
}
// Create the sample shop.
final Shop shop = new ContainerShop(info.getLocation(), price, info.getItem(), p.getName());
// This must be called after the event has been called.
// Else, if the event is cancelled, they won't get their
// money back.
if (tax != 0) {
if (!plugin.getEcon().withdraw(p.getName(), tax)) {
p.sendMessage(MsgUtil.p("you-cant-afford-a-new-shop", format(tax)));
return;
}
plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), tax);
}
final ShopCreateEvent e = new ShopCreateEvent(shop, p);
Bukkit.getPluginManager().callEvent(e);
if (e.isCancelled()) {
return;
}
shop.onLoad();
/* The shop has hereforth been successfully created */
createShop(shop);
p.sendMessage(MsgUtil.p("success-created-shop"));
final Location loc = shop.getLocation();
plugin.log(String.format("玩家: %s 创建了一个 %s 商店 在 (%s - %s, %s, %s)", p.getName(), shop.getDataName(), loc.getWorld().getName(), loc.getX(), loc.getY(), loc.getZ()));
if (!plugin.getConfig().getBoolean("shop.lock")) {
// Warn them if they haven't been warned since
// reboot
final Set<String> warings = plugin.getConfigManager().getWarnings();
if (!warings.contains(p.getName())) {
p.sendMessage(MsgUtil.p("shops-arent-locked"));
warings.add(p.getName());
}
}
// Figures out which way we should put the sign on and
// sets its text.
if (info.getSignBlock() != null && info.getSignBlock().getType() == Material.AIR && plugin.getConfig().getBoolean("shop.auto-sign")) {
final BlockState bs = info.getSignBlock().getState();
final BlockFace bf = info.getLocation().getBlock().getFace(info.getSignBlock());
bs.setType(Material.WALL_SIGN);
final Sign sign = (Sign) bs.getData();
sign.setFacingDirection(bf);
PluginKit.runTask(new Runnable() {
@Override
public void run() {
bs.update(true);
}
});
shop.setSignText();
}
if (shop instanceof ContainerShop) {
final ContainerShop cs = (ContainerShop) shop;
if (cs.isDoubleShop()) {
final Shop nextTo = cs.getAttachedShop();
if (nextTo.getPrice() > shop.getPrice()) {
// The one next to it must always be a
// buying shop.
p.sendMessage(MsgUtil.p("buying-more-than-selling"));
}
}
}
}
/* They didn't enter a number. */
catch (final NumberFormatException ex) {
p.sendMessage(MsgUtil.p("shop-creation-cancelled"));
return;
}
}
/* Purchase Handling */
else if (info.getAction() == ShopAction.BUY)
{
create(p, info, message);
} else if (/* Purchase Handling */info.getAction() == ShopAction.BUY) {
int amount = 0;
try {
amount = Integer.parseInt(message);
@ -347,140 +245,15 @@ public class ShopManager {
return;
}
if (shop.isSelling()) {
final int stock = shop.getRemainingStock();
if (stock < amount) {
p.sendMessage(MsgUtil.p("shop-stock-too-low", "" + shop.getRemainingStock(), 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;
}
final int pSpace = Util.countSpace(p.getInventory(), shop.getItem());
if (amount > pSpace) {
p.sendMessage(MsgUtil.p("not-enough-space", "" + pSpace));
return;
}
final ShopPurchaseEvent e = new ShopPurchaseEvent(shop, p, amount);
Bukkit.getPluginManager().callEvent(e);
if (e.isCancelled()) {
return; // Cancelled
}
// Money handling
if (!p.getName().equals(shop.getOwner())) {
// Check their balance. Works with *most* economy
// plugins*
if (plugin.getEcon().getBalance(p.getName()) < amount * shop.getPrice()) {
p.sendMessage(MsgUtil.p("you-cant-afford-to-buy", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(p.getName()))));
return;
}
// 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 (!plugin.getEcon().withdraw(p.getName(), total)) {
p.sendMessage(MsgUtil.p("you-cant-afford-to-buy", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(p.getName()))));
return;
}
if (!shop.isUnlimited() || plugin.getConfig().getBoolean("shop.pay-unlimited-shop-owners")) {
plugin.getEcon().deposit(shop.getOwner(), total * (1 - tax));
if (tax != 0) {
plugin.getEcon().deposit(plugin.getConfigManager().getTaxAccount(), total * tax);
}
}
// Notify the shop owner
if (plugin.getConfigManager().isShowTax()) {
String msg = MsgUtil.p("player-bought-from-your-store-tax", p.getName(), "" + amount, shop.getDataName(), Util.format((tax * total)));
if (stock == amount) {
msg += "\n"
+ MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), shop.getDataName());
}
MsgUtil.send(shop.getOwner(), msg);
} else {
String msg = MsgUtil.p("player-bought-from-your-store", p.getName(), "" + amount, shop.getDataName());
if (stock == amount) {
msg += "\n"
+ MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), shop.getDataName());
}
MsgUtil.send(shop.getOwner(), msg);
}
}
// Transfers the item from A to B
shop.sell(p, amount);
MsgUtil.sendPurchaseSuccess(p, shop, amount);
plugin.log(String.format("玩家: %s 从 %s 购买了 %s 件商品 花费 %s", p.getName(), shop.toString(), amount, shop.getPrice() * amount));
sale(p, shop, 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));
buy(p, shop, amount);
}
shop.setSignText(); // Update the signs count
}
/* If it was already cancelled (from destroyed) */
else
{
} else {
/* If it was already cancelled (from destroyed) */
return; // It was cancelled, go away.
}
}
/**
@ -527,7 +300,7 @@ public class ShopManager {
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);
inWorld = new HashMap<>(3);
// Put it in the data universe
this.getShops().put(world, inWorld);
}
@ -540,7 +313,7 @@ public class ShopManager {
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);
inChunk = new HashMap<>(1);
// Put it in the world
inWorld.put(shopChunk, inChunk);
}
@ -548,6 +321,233 @@ public class ShopManager {
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 {
// Checking the shop can be created
if (plugin.getShopManager().getShop(info.getLocation()) != null) {
p.sendMessage(MsgUtil.p("shop-already-owned"));
return;
}
if (Util.getSecondHalf(info.getLocation().getBlock()) != null && !p.hasPermission("quickshop.create.double")) {
p.sendMessage(MsgUtil.p("no-double-chests"));
return;
}
if (Util.canBeShop(info.getLocation().getBlock()) == false) {
p.sendMessage(MsgUtil.p("chest-was-removed"));
return;
}
// Price per item
double price;
if (plugin.getConfig().getBoolean("whole-number-prices-only")) {
price = Integer.parseInt(message);
} else {
price = Double.parseDouble(message);
}
if (price < 0.01) {
p.sendMessage(MsgUtil.p("price-too-cheap"));
return;
}
final double tax = plugin.getConfig().getDouble("shop.cost");
// Tax refers to the cost to create a shop. Not actual
// tax, that would be silly
if (tax != 0 && plugin.getEcon().getBalance(p.getName()) < tax) {
p.sendMessage(MsgUtil.p("you-cant-afford-a-new-shop", format(tax)));
return;
}
// Create the sample shop.
final Shop shop = new ContainerShop(info.getLocation(), price, info.getItem(), p.getName());
// This must be called after the event has been called.
// Else, if the event is cancelled, they won't get their
// money back.
if (tax != 0) {
if (!plugin.getEcon().withdraw(p.getName(), tax)) {
p.sendMessage(MsgUtil.p("you-cant-afford-a-new-shop", format(tax)));
return;
}
plugin.getEcon().deposit(plugin.getConfig().getString("tax-account"), tax);
}
final ShopCreateEvent e = new ShopCreateEvent(shop, p);
Bukkit.getPluginManager().callEvent(e);
if (e.isCancelled()) {
return;
}
shop.onLoad();
/* The shop has hereforth been successfully created */
createShop(shop);
p.sendMessage(MsgUtil.p("success-created-shop"));
final Location loc = shop.getLocation();
plugin.log(String.format("玩家: %s 创建了一个 %s 商店 在 (%s - %s, %s, %s)", p.getName(), shop.getDataName(), loc.getWorld().getName(), loc.getX(), loc.getY(), loc.getZ()));
if (!plugin.getConfig().getBoolean("shop.lock")) {
// Warn them if they haven't been warned since
// reboot
final Set<String> warings = plugin.getConfigManager().getWarnings();
if (!warings.contains(p.getName())) {
p.sendMessage(MsgUtil.p("shops-arent-locked"));
warings.add(p.getName());
}
}
// Figures out which way we should put the sign on and
// sets its text.
if (info.getSignBlock() != null && info.getSignBlock().getType() == Material.AIR && plugin.getConfig().getBoolean("shop.auto-sign")) {
final BlockState bs = info.getSignBlock().getState();
final BlockFace bf = info.getLocation().getBlock().getFace(info.getSignBlock());
bs.setType(Material.WALL_SIGN);
final Sign sign = (Sign) bs.getData();
sign.setFacingDirection(bf);
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
bs.update(true);
}
});
shop.setSignText();
}
if (shop instanceof ContainerShop) {
final ContainerShop cs = (ContainerShop) shop;
if (cs.isDoubleShop()) {
final Shop nextTo = cs.getAttachedShop();
if (nextTo.getPrice() > shop.getPrice()) {
// The one next to it must always be a
// buying shop.
p.sendMessage(MsgUtil.p("buying-more-than-selling"));
}
}
}
}
/* They didn't enter a number. */
catch (final NumberFormatException ex) {
p.sendMessage(MsgUtil.p("shop-creation-cancelled"));
return;
}
}
private void sale(final Player p, final Shop shop, final int amount) {
final int stock = shop.getRemainingStock();
if (stock < amount) {
p.sendMessage(MsgUtil.p("shop-stock-too-low", "" + shop.getRemainingStock(), 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;
}
final int pSpace = Util.countSpace(p.getInventory(), shop.getItem());
if (amount > pSpace) {
p.sendMessage(MsgUtil.p("not-enough-space", "" + pSpace));
return;
}
final ShopPurchaseEvent e = new ShopPurchaseEvent(shop, p, amount);
Bukkit.getPluginManager().callEvent(e);
if (e.isCancelled()) {
return; // Cancelled
}
// Money handling
if (!p.getName().equals(shop.getOwner())) {
// Check their balance. Works with *most* economy
// plugins*
if (plugin.getEcon().getBalance(p.getName()) < amount * shop.getPrice()) {
p.sendMessage(MsgUtil.p("you-cant-afford-to-buy", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(p.getName()))));
return;
}
// 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 (!plugin.getEcon().withdraw(p.getName(), total)) {
p.sendMessage(MsgUtil.p("you-cant-afford-to-buy", format(amount * shop.getPrice()), format(plugin.getEcon().getBalance(p.getName()))));
return;
}
if (!shop.isUnlimited() || plugin.getConfig().getBoolean("shop.pay-unlimited-shop-owners")) {
plugin.getEcon().deposit(shop.getOwner(), total * (1 - tax));
if (tax != 0) {
plugin.getEcon().deposit(plugin.getConfigManager().getTaxAccount(), total * tax);
}
}
// Notify the shop owner
if (plugin.getConfigManager().isShowTax()) {
String msg = MsgUtil.p("player-bought-from-your-store-tax", p.getName(), "" + amount, shop.getDataName(), Util.format((tax * total)));
if (stock == amount) {
msg += "\n" + MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), shop.getDataName());
}
MsgUtil.send(shop.getOwner(), msg);
} else {
String msg = MsgUtil.p("player-bought-from-your-store", p.getName(), "" + amount, shop.getDataName());
if (stock == amount) {
msg += "\n" + MsgUtil.p("shop-out-of-stock", "" + shop.getLocation().getBlockX(), "" + shop.getLocation().getBlockY(), "" + shop.getLocation().getBlockZ(), shop.getDataName());
}
MsgUtil.send(shop.getOwner(), msg);
}
}
// Transfers the item from A to B
shop.sell(p, amount);
MsgUtil.sendPurchaseSuccess(p, shop, amount);
plugin.log(String.format("玩家: %s 从 %s 购买了 %s 件商品 花费 %s", p.getName(), shop.toString(), amount, shop.getPrice() * amount));
}
public class ShopIterator implements Iterator<Shop> {
private Iterator<HashMap<Location, Shop>> chunks;
private Shop current;

View File

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

View File

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