Adjust command costs so that they are only charged after checking that the command can be used, adjust itemcost algorithm

This commit is contained in:
fullwall 2023-03-16 22:01:04 +08:00
parent b35c815629
commit 46633409c3
8 changed files with 143 additions and 47 deletions

View File

@ -335,6 +335,8 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
.relocate("net{}kyori", "clib{}net{}kyori").build());
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("examination-string").version("1.3.0")
.relocate("net{}kyori", "clib{}net{}kyori").build());
lib.loadLibrary(Library.builder().groupId("org{}joml").artifactId("joml").version("1.10.5")
.relocate("org{}joml", "clib{}org{}joml").build());
}
@Override

View File

@ -541,8 +541,8 @@ public class NPCCommands {
commands.setCost(args.getDouble(2));
Messaging.sendTr(sender, Messages.COMMAND_COST_SET, args.getDouble(2));
} else if (action.equalsIgnoreCase("expcost")) {
commands.setExperienceCost((float) args.getDouble(2));
Messaging.sendTr(sender, Messages.COMMAND_EXPERIENCE_COST_SET, args.getDouble(2));
commands.setExperienceCost(args.getInteger(2));
Messaging.sendTr(sender, Messages.COMMAND_EXPERIENCE_COST_SET, args.getInteger(2));
} else if (action.equalsIgnoreCase("hideerrors")) {
commands.setHideErrorMessages(!commands.isHideErrorMessages());
Messaging.sendTr(sender, commands.isHideErrorMessages() ? Messages.COMMAND_HIDE_ERROR_MESSAGES_SET

View File

@ -36,6 +36,7 @@ import net.citizensnpcs.api.astar.pathfinder.MinecraftBlockExaminer;
import net.citizensnpcs.api.astar.pathfinder.SwimmingExaminer;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.SpigotUtil;
import net.citizensnpcs.npc.ai.AStarNavigationStrategy.AStarPlanner;
import net.citizensnpcs.npc.ai.MCNavigationStrategy.MCNavigator;
import net.citizensnpcs.trait.RotationTrait;
@ -498,7 +499,7 @@ public class CitizensNavigator implements Navigator, Runnable {
if (localParams.stationaryTicks() < 0)
return false;
Location current = npc.getEntity().getLocation(STATIONARY_LOCATION);
if (current.getY() < -6) {
if (!SpigotUtil.checkYSafe(current.getY(), current.getWorld())) {
stopNavigating(CancelReason.STUCK);
return true;
}

View File

@ -23,7 +23,6 @@ import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.plugin.RegisteredServiceProvider;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
@ -48,10 +47,14 @@ import net.citizensnpcs.api.trait.TraitName;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.api.util.Translator;
import net.citizensnpcs.trait.shop.ExperienceAction;
import net.citizensnpcs.trait.shop.ItemAction;
import net.citizensnpcs.trait.shop.MoneyAction;
import net.citizensnpcs.trait.shop.NPCShopAction;
import net.citizensnpcs.trait.shop.NPCShopAction.Transaction;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.StringHelper;
import net.citizensnpcs.util.Util;
import net.milkbowl.vault.economy.Economy;
@TraitName("commandtrait")
public class CommandTrait extends Trait {
@ -66,7 +69,7 @@ public class CommandTrait extends Trait {
@Persist
private ExecutionMode executionMode = ExecutionMode.LINEAR;
@Persist
private float experienceCost = -1;
private int experienceCost = -1;
@Persist(valueType = Long.class)
private final Map<String, Long> globalCooldowns = Maps.newHashMap();
@Persist
@ -90,50 +93,29 @@ public class CommandTrait extends Trait {
return id;
}
private boolean chargeCommandCosts(Player player, Hand hand) {
private Transaction chargeCommandCosts(Player player, Hand hand) {
NPCShopAction action = null;
if (cost > 0) {
try {
RegisteredServiceProvider<Economy> provider = Bukkit.getServicesManager()
.getRegistration(Economy.class);
if (provider != null && provider.getProvider() != null) {
Economy economy = provider.getProvider();
if (!economy.has(player, cost)) {
sendErrorMessage(player, CommandTraitError.MISSING_MONEY, null, cost);
return false;
}
economy.withdrawPlayer(player, cost);
}
} catch (NoClassDefFoundError e) {
Messaging.severe("Unable to find Vault when checking command cost - is it installed?");
action = new MoneyAction(cost);
if (!action.take(player).isPossible()) {
sendErrorMessage(player, CommandTraitError.MISSING_MONEY, null, cost);
}
}
if (experienceCost > 0) {
if (player.getLevel() < experienceCost) {
action = new ExperienceAction(experienceCost);
if (!action.take(player).isPossible()) {
sendErrorMessage(player, CommandTraitError.MISSING_EXPERIENCE, null, experienceCost);
return false;
}
player.setLevel((int) (player.getLevel() - experienceCost));
}
if (itemRequirements.size() > 0) {
List<ItemStack> req = Lists.newArrayList(itemRequirements);
Inventory tempInventory = Bukkit.createInventory(null, 54);
for (int i = 0; i < player.getInventory().getSize(); i++) {
tempInventory.setItem(i, player.getInventory().getItem(i));
}
for (ItemStack stack : req) {
if (tempInventory.containsAtLeast(stack, stack.getAmount())) {
tempInventory.removeItem(stack);
} else {
sendErrorMessage(player, CommandTraitError.MISSING_ITEM, null, Util.prettyEnum(stack.getType()),
stack.getAmount());
return false;
}
}
for (int i = 0; i < player.getInventory().getSize(); i++) {
player.getInventory().setItem(i, tempInventory.getItem(i));
action = new ItemAction(itemRequirements);
if (!action.take(player).isPossible()) {
ItemStack stack = itemRequirements.get(0);
sendErrorMessage(player, CommandTraitError.MISSING_ITEM, null, Util.prettyEnum(stack.getType()),
stack.getAmount());
}
}
return true;
return action == null ? Transaction.success() : action.take(player);
}
public void clearHistory(CommandTraitError which, Player who) {
@ -288,16 +270,22 @@ public class CommandTrait extends Trait {
|| PlayerNPCCommand.requiresTracking(command))) {
playerTracking.put(player.getUniqueId(), info = new PlayerNPCCommand());
}
if (info != null && !info.canUse(CommandTrait.this, player, command)) {
return;
}
Transaction charge = null;
if (charged == null) {
if (!chargeCommandCosts(player, hand)) {
charge = chargeCommandCosts(player, hand);
if (!charge.isPossible()) {
charged = false;
return;
}
charged = true;
}
if (info != null && !info.canUse(CommandTrait.this, player, command))
return;
if (charged == null) {
charge.run();
}
PermissionAttachment attachment = player.addAttachment(CitizensAPI.getPlugin());
if (temporaryPermissions.size() > 0) {
for (String permission : temporaryPermissions) {
@ -406,7 +394,7 @@ public class CommandTrait extends Trait {
this.executionMode = mode;
}
public void setExperienceCost(float experienceCost) {
public void setExperienceCost(int experienceCost) {
this.experienceCost = experienceCost;
}

View File

@ -48,6 +48,8 @@ import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.api.util.Placeholders;
import net.citizensnpcs.trait.shop.CommandAction;
import net.citizensnpcs.trait.shop.CommandAction.CommandActionGUI;
import net.citizensnpcs.trait.shop.ExperienceAction;
import net.citizensnpcs.trait.shop.ExperienceAction.ExperienceActionGUI;
import net.citizensnpcs.trait.shop.ItemAction;
import net.citizensnpcs.trait.shop.ItemAction.ItemActionGUI;
import net.citizensnpcs.trait.shop.MoneyAction;
@ -714,5 +716,6 @@ public class ShopTrait extends Trait {
NPCShopAction.register(PermissionAction.class, "permissions", new PermissionActionGUI());
NPCShopAction.register(MoneyAction.class, "money", new MoneyActionGUI());
NPCShopAction.register(CommandAction.class, "command", new CommandActionGUI());
NPCShopAction.register(ExperienceAction.class, "experience", new ExperienceActionGUI());
}
}

View File

@ -0,0 +1,92 @@
package net.citizensnpcs.trait.shop;
import java.util.function.Consumer;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import net.citizensnpcs.api.gui.InputMenus;
import net.citizensnpcs.api.gui.InventoryMenuPage;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.util.Util;
public class ExperienceAction extends NPCShopAction {
@Persist
public int exp;
public ExperienceAction() {
}
public ExperienceAction(int cost) {
this.exp = cost;
}
@Override
public String describe() {
return exp + " XP";
}
@Override
public Transaction grant(Entity entity) {
if (!(entity instanceof Player))
return Transaction.fail();
Player player = (Player) entity;
return Transaction.create(() -> {
return true;
}, () -> {
player.setLevel(player.getLevel() + exp);
}, () -> {
player.setLevel(player.getLevel() - exp);
});
}
@Override
public Transaction take(Entity entity) {
if (!(entity instanceof Player))
return Transaction.fail();
Player player = (Player) entity;
return Transaction.create(() -> {
return player.getLevel() >= exp;
}, () -> {
player.setLevel(player.getLevel() - exp);
}, () -> {
player.setLevel(player.getLevel() + exp);
});
}
public static class ExperienceActionGUI implements GUI {
@Override
public InventoryMenuPage createEditor(NPCShopAction previous, Consumer<NPCShopAction> callback) {
final ExperienceAction action = previous == null ? new ExperienceAction() : (ExperienceAction) previous;
return InputMenus.filteredStringSetter(() -> Integer.toString(action.exp), s -> {
try {
int result = Integer.parseInt(s);
if (result < 0)
return false;
action.exp = result;
} catch (NumberFormatException nfe) {
return false;
}
callback.accept(action);
return true;
});
}
@Override
public ItemStack createMenuItem(NPCShopAction previous) {
String description = null;
if (previous != null) {
ExperienceAction old = (ExperienceAction) previous;
description = old.describe();
}
return Util.createItem(Material.EXPERIENCE_BOTTLE, "Experience", description);
}
@Override
public boolean manages(NPCShopAction action) {
return action instanceof ExperienceAction;
}
}
}

View File

@ -21,6 +21,10 @@ public class MoneyAction extends NPCShopAction {
public MoneyAction() {
}
public MoneyAction(double cost) {
this.money = cost;
}
@Override
public String describe() {
Economy economy = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider();

View File

@ -64,7 +64,13 @@ public abstract class NPCShopAction implements Cloneable {
}
public static Transaction fail() {
return new Transaction(() -> false, () -> {
return create(() -> false, () -> {
}, () -> {
});
}
public static Transaction success() {
return create(() -> true, () -> {
}, () -> {
});
}