Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement kits placing items in specific slots #5794

Open
wants to merge 1 commit into
base: 2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
172 changes: 124 additions & 48 deletions Essentials/src/main/java/com/earth2me/essentials/Kit.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.stream.Collectors;

import static com.earth2me.essentials.I18n.tlLiteral;

Expand Down Expand Up @@ -127,10 +128,10 @@ public long getNextUse(final User user) throws Exception {

@Deprecated
public List<String> getItems(final User user) throws Exception {
return getItems();
return getBasicItems();
}

public List<String> getItems() throws Exception {
public List<String> getBasicItems() throws Exception {
if (kit == null) {
throw new TranslatableException("kitNotFound");
}
Expand All @@ -154,14 +155,46 @@ public List<String> getItems() throws Exception {
}
}

public List<String> getGearItems() throws Exception {
if (kit == null) {
throw new TranslatableException("kitNotFound");
}
try {
final List<String> itemList = new ArrayList<>();
final String[] gearConfigName = {"boots", "leggings", "chestplate", "helmet", "offhand"};
for (String itemName : gearConfigName) {
final Object item = kit.get(itemName);
if (item == null) {
itemList.add(null);
continue;
}

if (item instanceof String) {
itemList.add(item.toString());
continue;
}
throw new Exception("Invalid kit item: " + item.toString());
}

return itemList;
} catch (final Exception e) {
ess.getLogger().log(Level.WARNING, "Error parsing kit " + kitName + ": " + e.getMessage());
throw new TranslatableException(e,"kitError2");
}
}

public boolean expandItems(final User user) throws Exception {
return expandItems(user, getItems(user));
return expandItems(user, getItems(user), getGearItems());
}

public boolean expandItems(final User user, final List<String> items) throws Exception {
public boolean expandItems(final User user, final List<String> items, final List<String> gearItems) throws Exception {
try {
final IText input = new SimpleTextInput(items);
final IText output = new KeywordReplacer(input, user.getSource(), ess, true, true);
final IText basicInput = new SimpleTextInput(items);
final IText basicOutput = new KeywordReplacer(basicInput, user.getSource(), ess, true, true);

final List<String> nonNullGearItems = gearItems.stream().filter(is -> is != null).collect(Collectors.toList());
final IText gearInput = new SimpleTextInput(nonNullGearItems);
final IText gearOutput = new KeywordReplacer(gearInput, user.getSource(), ess, true, true);

final KitClaimEvent event = new KitClaimEvent(user, this);
Bukkit.getPluginManager().callEvent(event);
Expand All @@ -173,58 +206,29 @@ public boolean expandItems(final User user, final List<String> items) throws Exc
final boolean allowUnsafe = ess.getSettings().allowUnsafeEnchantments();
final boolean autoEquip = ess.getSettings().isKitAutoEquip();
final List<ItemStack> itemList = new ArrayList<>();
final List<ItemStack> gearList = new ArrayList<>();
final List<String> commandQueue = new ArrayList<>();
final List<String> moneyQueue = new ArrayList<>();
final String currencySymbol = ess.getSettings().getCurrencySymbol().isEmpty() ? "$" : ess.getSettings().getCurrencySymbol();
for (final String kitItem : output.getLines()) {
if (kitItem.startsWith("$") || kitItem.startsWith(currencySymbol)) {
moneyQueue.add(NumberUtil.sanitizeCurrencyString(kitItem, ess));
continue;
}

if (kitItem.startsWith("/")) {
String command = kitItem.substring(1);
final String name = user.getName();
command = command.replace("{player}", name);
commandQueue.add(command);
continue;
}

final ItemStack stack;

if (kitItem.startsWith("@")) {
if (ess.getSerializationProvider() == null) {
ess.getLogger().log(Level.WARNING, AdventureUtil.miniToLegacy(tlLiteral("kitError3", kitName, user.getName())));
continue;
}
stack = ess.getSerializationProvider().deserializeItem(Base64Coder.decodeLines(kitItem.substring(1)));
} else {
final String[] parts = kitItem.split(" +");
final ItemStack parseStack = ess.getItemDb().get(parts[0], parts.length > 1 ? Integer.parseInt(parts[1]) : 1);

if (parseStack.getType() == Material.AIR) {
continue;
}

final MetaItemStack metaStack = new MetaItemStack(parseStack);

if (parts.length > 2) {
// We pass a null sender here because kits should not do perm checks
metaStack.parseStringMeta(null, allowUnsafe, parts, 2, ess);
}

stack = metaStack.getItemStack();
}

itemList.add(stack);
}
populateKitLists(user, basicOutput, moneyQueue, commandQueue, itemList, allowUnsafe, currencySymbol);
populateKitLists(user, gearOutput, moneyQueue, commandQueue, gearList, allowUnsafe, currencySymbol);

final int maxStackSize = user.isAuthorized("essentials.oversizedstacks") ? ess.getSettings().getOversizedStackSize() : 0;
final boolean isDropItemsIfFull = ess.getSettings().isDropItemsIfFull();

final KitPreExpandItemsEvent itemsEvent = new KitPreExpandItemsEvent(user, kitName, itemList);
final List<ItemStack> totalItems = new ArrayList<>(itemList);
totalItems.addAll(gearList.stream().filter(is -> is != null).collect(Collectors.toList()));
final KitPreExpandItemsEvent itemsEvent = new KitPreExpandItemsEvent(user, kitName, totalItems);
Bukkit.getPluginManager().callEvent(itemsEvent);

final List<Integer> nullGearItemsIndexes = findNullIndexes(gearItems);

final ItemStack[] gearArray = addNullIndexes(gearList, nullGearItemsIndexes).toArray(new ItemStack[0]);
final List<ItemStack> leftovers = Inventories.addGear(user.getBase(), gearArray);

itemList.addAll(leftovers);

final ItemStack[] itemArray = itemList.toArray(new ItemStack[0]);

if (!isDropItemsIfFull && !Inventories.hasSpace(user.getBase(), maxStackSize, autoEquip, itemArray)) {
Expand Down Expand Up @@ -274,4 +278,76 @@ public boolean expandItems(final User user, final List<String> items) throws Exc
}
return true;
}

private void populateKitLists(User user, IText output, List<String> moneyQueue, List<String> commandQueue, List<ItemStack> itemList, boolean allowUnsafe, String currencySymbol) throws Exception {
for (final String kitItem : output.getLines()) {
if (kitItem.startsWith(currencySymbol)) {
moneyQueue.add(NumberUtil.sanitizeCurrencyString(kitItem, ess));
continue;
}

if (kitItem.startsWith("/")) {
String command = kitItem.substring(1);
final String name = user.getName();
command = command.replace("{player}", name);
commandQueue.add(command);
continue;
}

final ItemStack stack = parseItemStack(kitItem, user, allowUnsafe);
if (stack == null) {
continue;
}

itemList.add(stack);
}
}

private ItemStack parseItemStack(String kitItem, User user, boolean allowUnsafe) throws Exception {
if (kitItem.startsWith("@")) {
if (ess.getSerializationProvider() == null) {
ess.getLogger().log(Level.WARNING, AdventureUtil.miniToLegacy(tlLiteral("kitError3", kitName, user.getName())));
return null;
}
return ess.getSerializationProvider().deserializeItem(Base64Coder.decodeLines(kitItem.substring(1)));
} else {
final String[] parts = kitItem.split(" +");
final ItemStack parseStack = ess.getItemDb().get(parts[0], parts.length > 1 ? Integer.parseInt(parts[1]) : 1);

if (parseStack.getType() == Material.AIR) {
return null;
}

final MetaItemStack metaStack = new MetaItemStack(parseStack);

if (parts.length > 2) {
// We pass a null sender here because kits should not do perm checks
metaStack.parseStringMeta(null, allowUnsafe, parts, 2, ess);
}

return metaStack.getItemStack();
}
}

private List<Integer> findNullIndexes(List<String> list) {
final List<Integer> nullIndexes = new ArrayList<>();

for (int i = 0; i < list.size(); i++) {
if (list.get(i) == null) {
nullIndexes.add(i);
}
}

return nullIndexes;
}

private List<ItemStack> addNullIndexes(List<ItemStack> list, List<Integer> nullIndexes) {
final List<ItemStack> newList = new ArrayList<>(list);

for (int nullIndex : nullIndexes) {
newList.add(nullIndex, null);
}

return newList;
}
}
13 changes: 11 additions & 2 deletions Essentials/src/main/java/com/earth2me/essentials/Kits.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,20 @@ public String matchKit(final String name) {
return null;
}

public void addKit(String name, final List<String> lines, final long delay) {
public void addKit(String name, final List<String> basicLines, final List<String> gearLines, final long delay) {
name = name.replace('.', '_').replace('/', '_').toLowerCase(Locale.ENGLISH);
// Will overwrite but w/e
rootConfig.setProperty("kits." + name + ".delay", delay);
rootConfig.setProperty("kits." + name + ".items", lines);
rootConfig.setProperty("kits." + name + ".items", basicLines);

final String[] gearConfigName = {"boots", "leggings", "chestplate", "helmet", "offhand"};
for (int i = 0; i < gearLines.size(); i++) {
final String gearLine = gearLines.get(i);
if (gearLine != null) {
rootConfig.setProperty("kits." + name + "." + gearConfigName[i], gearLine);
}
}

parseKits();
rootConfig.save();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ public void run(final Server server, final User user, final String commandLabel,
// Command handler will auto fail if this fails.
final long delay = Long.parseLong(args[1]);
final String kitname = args[0];
final ItemStack[] items = Inventories.getInventory(user.getBase(), true);
final ItemStack[] items = Inventories.getInventoryBasicContents(user.getBase());
final ItemStack[] gear = Inventories.getInventoryGear(user.getBase());
final List<String> list = new ArrayList<>();
final List<String> gearList = new ArrayList<>();

boolean useSerializationProvider = ess.getSettings().isUseBetterKits();

Expand All @@ -50,26 +52,43 @@ public void run(final Server server, final User user, final String commandLabel,
}

for (ItemStack is : items) {
if (is != null && is.getType() != null && is.getType() != Material.AIR) {
final String serialized;
if (useSerializationProvider) {
serialized = "@" + Base64Coder.encodeLines(ess.getSerializationProvider().serializeItem(is));
} else {
serialized = ess.getItemDb().serialize(is);
}
final String serialized = serializeItem(is, useSerializationProvider);
if (serialized != null) {
list.add(serialized);
}
}

int gearItemsAmount = 0;
for (ItemStack is : gear) {
gearItemsAmount = is == null ? gearItemsAmount : gearItemsAmount + 1;
gearList.add(serializeItem(is, useSerializationProvider));
}

// Some users might want to directly write to config knowing the consequences. *shrug*
if (!ess.getSettings().isPastebinCreateKit()) {
ess.getKits().addKit(kitname, list, delay);
user.sendTl("createdKit", kitname, list.size(), delay);
ess.getKits().addKit(kitname, list, gearList, delay);
user.sendTl("createdKit", kitname, list.size() + gearItemsAmount, delay);
} else {
uploadPaste(user.getSource(), kitname, delay, list);
uploadPaste(user.getSource(), kitname, delay, list, gearList);
}
}

private void uploadPaste(final CommandSource sender, final String kitName, final long delay, final List<String> list) {
private String serializeItem(ItemStack is, boolean useSerializationProvider) {
if (is != null && is.getType() != null && is.getType() != Material.AIR) {
final String serialized;
if (useSerializationProvider) {
serialized = "@" + Base64Coder.encodeLines(ess.getSerializationProvider().serializeItem(is));
} else {
serialized = ess.getItemDb().serialize(is);
}

return serialized;
}

return null;
}

private void uploadPaste(final CommandSource sender, final String kitName, final long delay, final List<String> list, final List<String> gearList) {
ess.runTaskAsynchronously(() -> {
try {
final StringWriter sw = new StringWriter();
Expand All @@ -79,6 +98,14 @@ private void uploadPaste(final CommandSource sender, final String kitName, final
config.node("kits", kitName, "delay").set(delay);
config.node("kits", kitName, "items").set(list);

final String[] gearConfigName = {"boots", "leggings", "chestplate", "helmet", "offhand"};
for (int i = 0; i < gearList.size(); i++) {
final String gearLine = gearList.get(i);
if (gearLine != null) {
config.node("kits", kitName, gearConfigName[i]).set(gearList.get(i));
}
}

sw.append("# Copy the kit code below into the kits section in your config.yml file\n");
loader.save(config);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

public class Commandshowkit extends EssentialsCommand {
public Commandshowkit() {
Expand All @@ -22,7 +23,11 @@ public void run(final Server server, final User user, final String commandLabel,

for (final String kitName : args[0].toLowerCase(Locale.ENGLISH).split(",")) {
user.sendTl("kitContains", kitName);
for (final String s : new Kit(kitName, ess).getItems()) {
final Kit kit = new Kit(kitName, ess);
for (final String s : kit.getBasicItems()) {
user.sendTl("kitItem", s);
}
for (final String s : kit.getGearItems().stream().filter(is -> is != null).collect(Collectors.toList())) {
user.sendTl("kitItem", s);
}
}
Expand Down