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

Adds Loot Tables #7242

Merged
merged 67 commits into from
Dec 24, 2024
Merged
Changes from 51 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
e9f97f8
Add Loot Tables
Burbulinis Dec 3, 2024
7a144b7
Optimize Imports
Burbulinis Dec 4, 2024
11b69c1
Fix docs and add a registry class info
Burbulinis Dec 4, 2024
a6cdeea
Changes
Burbulinis Dec 4, 2024
ea1a3da
remove license thing
Burbulinis Dec 4, 2024
097e56a
Add converter for LootTables - LootTable,
Burbulinis Dec 4, 2024
6294fee
add tests ? unsure if theyre correct and add expressions to get luck/…
Burbulinis Dec 4, 2024
a4bdced
Replace current implementation to module, add NameSpacedUtils class f…
Burbulinis Dec 5, 2024
e261ee8
Add docs, optimize imports and changes
Burbulinis Dec 6, 2024
458bf88
Change syntax and add some tests
Burbulinis Dec 6, 2024
b295696
Fix docs, fix tests, replace paper methods to bukkit ones and changes
Burbulinis Dec 6, 2024
ce3ec4f
one silly thing hehe
Burbulinis Dec 6, 2024
c7777df
Add JUnit tests, fix tests and changes
Burbulinis Dec 7, 2024
554a705
Fix JUnit test
Burbulinis Dec 7, 2024
4d576cb
ok junit test
Burbulinis Dec 7, 2024
4f90a8e
fix tests
Burbulinis Dec 7, 2024
3bc7b69
Optimize imports and fix description of EffGenerateLoot and ExprLootI…
Burbulinis Dec 7, 2024
9acbcba
Clean up LootTableUtils and update docs
Burbulinis Dec 9, 2024
f261551
update tests
Burbulinis Dec 9, 2024
12b47dc
add loot table type in the default.lang file
Burbulinis Dec 9, 2024
01aa136
Fix the seed expression not actually updating the state
Burbulinis Dec 9, 2024
2da8311
optimize imports
Burbulinis Dec 9, 2024
e14ff8d
change exampled for loot table seed
Burbulinis Dec 9, 2024
2038063
Add default event value for LootTable in LootGenerate event
Burbulinis Dec 9, 2024
4dfb8d9
Add escape character for colons
Burbulinis Dec 15, 2024
70977bc
Merge branch 'dev/feature' into feature/loottable
Burbulinis Dec 15, 2024
cc92b1b
Add LootContext event value in LootGenerateEvent
Burbulinis Dec 15, 2024
01e38a1
Make cached loot context transient
Burbulinis Dec 15, 2024
9fc767c
changes
Burbulinis Dec 15, 2024
d6658aa
tests and fix docs
Burbulinis Dec 15, 2024
8620a07
Merge remote-tracking branch 'fork/feature/loottable' into feature/lo…
Burbulinis Dec 15, 2024
748b1b3
alot of things
Burbulinis Dec 15, 2024
00454e4
Merge branch 'dev/feature' into feature/loottable
Burbulinis Dec 15, 2024
22e23ac
Merge branch 'dev/feature' into feature/loottable
Burbulinis Dec 16, 2024
4902a64
fix toString
Burbulinis Dec 16, 2024
012569e
remove consumer
Burbulinis Dec 16, 2024
d7d36a5
fix tests
Burbulinis Dec 16, 2024
c11bd48
Merge remote-tracking branch 'fork/feature/loottable' into feature/lo…
Burbulinis Dec 16, 2024
cc3360d
optimize imports
Burbulinis Dec 16, 2024
1cfe536
Fix exception in Java 17
Burbulinis Dec 16, 2024
1886f5c
Merge branch 'dev/feature' into feature/loottable
Burbulinis Dec 18, 2024
0689496
Merge branch 'dev/feature' into feature/loottable
Moderocky Dec 18, 2024
31fc71b
hopefully one last thing
Burbulinis Dec 18, 2024
9dd4b85
Merge branch 'dev/feature' into feature/loottable
Burbulinis Dec 18, 2024
c83fb07
Merge remote-tracking branch 'fork/feature/loottable' into feature/lo…
Burbulinis Dec 18, 2024
6593731
Merge branch 'dev/feature' into feature/loottable
Burbulinis Dec 18, 2024
2959110
move LootGenerateEvent and event values to module class because idk w…
Burbulinis Dec 18, 2024
3d9f851
Merge remote-tracking branch 'fork/feature/loottable' into feature/lo…
Burbulinis Dec 18, 2024
85b2b43
Merge branch 'dev/feature' into feature/loottable
Efnilite Dec 19, 2024
4aa5bef
Merge branch 'dev/feature' into feature/loottable
Burbulinis Dec 19, 2024
f2d0e12
optimize imports and another one
Burbulinis Dec 19, 2024
6401905
pickel era changes
Burbulinis Dec 19, 2024
83e2a72
update tests
Burbulinis Dec 20, 2024
13d85a1
more pickel era changes
Burbulinis Dec 20, 2024
5eb4eee
Merge branch 'dev/feature' into feature/loottable
Burbulinis Dec 20, 2024
2e34c01
uh oh
Burbulinis Dec 20, 2024
43d7b4e
more uh ohs
Burbulinis Dec 20, 2024
4889905
Merge remote-tracking branch 'fork/feature/loottable' into feature/lo…
Burbulinis Dec 20, 2024
cceb192
even more uh ohs
Burbulinis Dec 20, 2024
9514b0b
we dont talk about it
Burbulinis Dec 20, 2024
abb8081
small changes
Burbulinis Dec 20, 2024
504558d
optimize le importos
Burbulinis Dec 20, 2024
7b1b606
even more pickel era changes
Burbulinis Dec 20, 2024
8c86cac
wow pickel has alot of changes
Burbulinis Dec 20, 2024
c244ab1
Move ExprLoot to module and clean it up
Burbulinis Dec 21, 2024
f9c11d4
changes
Burbulinis Dec 21, 2024
b2d3d47
Merge remote-tracking branch 'SkriptLang/dev/feature' into feature/lo…
Moderocky Dec 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/ch/njol/skript/Skript.java
Original file line number Diff line number Diff line change
@@ -98,6 +98,7 @@
import org.skriptlang.skript.bukkit.displays.DisplayModule;
import org.skriptlang.skript.bukkit.fishing.FishingModule;
import org.skriptlang.skript.bukkit.input.InputModule;
import org.skriptlang.skript.bukkit.loottables.LootTableModule;
import org.skriptlang.skript.lang.comparator.Comparator;
import org.skriptlang.skript.lang.comparator.Comparators;
import org.skriptlang.skript.lang.converter.Converter;
@@ -549,6 +550,7 @@ public void onEnable() {
BreedingModule.load();
DisplayModule.load();
InputModule.load();
LootTableModule.load();
} catch (final Exception e) {
exception(e, "Could not load required .class files: " + e.getLocalizedMessage());
setEnabled(false);
117 changes: 117 additions & 0 deletions src/main/java/ch/njol/skript/bukkitutil/NamespacedUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package ch.njol.skript.bukkitutil;

import ch.njol.skript.Skript;
import ch.njol.util.NonNullPair;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.NamespacedKey;
import org.jetbrains.annotations.NotNull;

import java.util.Locale;
import java.util.Set;

public class NamespacedUtils {

private static final Set<Character> LEGAL_NAMESPACE_CHARS = Set.of(ArrayUtils.toObject("abcdefghijklmnopqrstuvwxyz0123456789._-/".toCharArray()));

/**
* Gets a namespaced key in Skript's namespace if the namespace was not defined.
*
* @param key the unparsed key
* @return the resulting NamespacedKey
*/
public static NamespacedKey parseNamespacedKey(@NotNull String key) {
NamespacedKey namespacedKey = NamespacedKey.fromString(key, Skript.getInstance());
if (namespacedKey != null)
return namespacedKey;

return createNamespacedKey(key);
}

/**
* Creates a namespaced key in Skript's namespace encoded to avoid the character limitations of a normal key.
* This key will be created in Skript's namespace.
*
* @param key The key to use
* @return a NamespacedKey with the encoded key in corresponding Namespace
*/
private static NamespacedKey createNamespacedKey(@NotNull String key) {
StringBuilder encodedKeyBuilder = new StringBuilder();
// keys must be all lowercase
key = key.toLowerCase(Locale.ENGLISH).replace(' ', '_');
int keyLength = key.length();
for (int i = 0; i < keyLength; i++) {
char currentChar = key.charAt(i);
// if this character is legal to use in a namespace key
if (LEGAL_NAMESPACE_CHARS.contains(currentChar)) {
// if the original string had a ".x" in it, we need to escape it
// so decoding doesn't think it's a hex sequence
if (i != (keyLength - 1) && currentChar == '.' && key.charAt(i + 1) == 'x') {
i += 1; // skip the "x"
encodedKeyBuilder.append(".x");
encodedKeyBuilder.append(Integer.toHexString('.'));
encodedKeyBuilder.append(".x");
encodedKeyBuilder.append(Integer.toHexString('x'));
// if we're not at the end and the next char is a legal char, add the trailing dot
// to represent the end of the hex sequence
if (i != (keyLength - 1) && LEGAL_NAMESPACE_CHARS.contains(key.charAt(i + 1)))
encodedKeyBuilder.append('.');
} else {
// we are dealing with a legal character, so we can just append it
encodedKeyBuilder.append(currentChar);
}
} else {
// escape a colon, e.g. "foo+:bar" -> "skript:foo.x2b.x3a.bar", "foo+\:bar" -> "foo.x2b:bar"
if (currentChar == '\\' && i != (keyLength - 1) && key.charAt(i + 1) == ':') {
encodedKeyBuilder.append(':');
i++;
continue;
}
// add ".x(hex code)" to the encoded key
encodedKeyBuilder.append(".x");
encodedKeyBuilder.append(Integer.toHexString(currentChar));
// only add the trailing dot if the next character is a legal character
if (i != (keyLength - 1) && LEGAL_NAMESPACE_CHARS.contains(key.charAt(i + 1)))
encodedKeyBuilder.append('.');
}
}
return NamespacedKey.fromString(encodedKeyBuilder.toString(), Skript.getInstance());
}

/**
* Decodes a {@link NamespacedKey} encoded by {@link #parseNamespacedKey(String key)}.
*
* @param namespacedKey the namespaced key to decode
* @return a Pair with the first element as the namespace and the second as the decoded key
*/
public static NonNullPair<String, String> decodeNamespacedKey(NamespacedKey namespacedKey) {
String encodedKey = namespacedKey.getKey();
StringBuilder decodedKeyBuilder = new StringBuilder();
int encodedKeyLength = encodedKey.length();
int lastCharIndex = encodedKeyLength - 1;
for (int i = 0; i < encodedKeyLength; i++) {
char currentChar = encodedKey.charAt(i);
// if we are encountering a ".x" hex sequence
if (i != lastCharIndex && currentChar == '.' && encodedKey.charAt(i + 1) == 'x') {
i += 2; // skip the ".x" so it isn't part of our hex string
StringBuilder hexString = new StringBuilder();
// The hex sequence continues until a . is encountered or we reach the end of the string
while (i <= lastCharIndex && encodedKey.charAt(i) != '.') {
hexString.append(encodedKey.charAt(i));
i++;
}
// if the . was the start of another ".x" hex sequence, back up by 1 character
if (i <= lastCharIndex && encodedKey.charAt(i + 1) == 'x')
i--;
// parse the hex sequence to a char
char decodedChar = (char) Long.parseLong(hexString.toString(), 16);
decodedKeyBuilder.append(decodedChar);
} else {
// this is just a normal character, not a hex sequence
// so we can just append it
decodedKeyBuilder.append(currentChar);
}
}
return new NonNullPair<>(namespacedKey.getNamespace(), decodedKeyBuilder.toString());
}

}
Original file line number Diff line number Diff line change
@@ -1629,24 +1629,6 @@ public ItemType get(PlayerStopUsingItemEvent event) {
}, EventValues.TIME_NOW);
}

// LootGenerateEvent
if (Skript.classExists("org.bukkit.event.world.LootGenerateEvent")) {
EventValues.registerEventValue(LootGenerateEvent.class, Entity.class, new Getter<Entity, LootGenerateEvent>() {
@Override
@Nullable
public Entity get(LootGenerateEvent event) {
return event.getEntity();
}
}, EventValues.TIME_NOW);
EventValues.registerEventValue(LootGenerateEvent.class, Location.class, new Getter<Location, LootGenerateEvent>() {
@Override
@Nullable
public Location get(LootGenerateEvent event) {
return event.getLootContext().getLocation();
}
}, EventValues.TIME_NOW);
}

// EntityResurrectEvent
EventValues.registerEventValue(EntityResurrectEvent.class, Slot.class, new Getter<Slot, EntityResurrectEvent>() {
@Override
16 changes: 1 addition & 15 deletions src/main/java/ch/njol/skript/events/SimpleEvents.java
Original file line number Diff line number Diff line change
@@ -620,21 +620,7 @@ public class SimpleEvents {
"\t\tset chat format to \"&lt;orange&gt;[player]&lt;light gray&gt;: &lt;white&gt;[message]\""
)
.since("1.4.1");
if (Skript.classExists("org.bukkit.event.world.LootGenerateEvent")) {
Skript.registerEvent("Loot Generate", SimpleEvent.class, LootGenerateEvent.class, "loot generat(e|ing)")
.description(
"Called when a loot table of an inventory is generated in the world.",
"For example, when opening a shipwreck chest."
)
.examples(
"on loot generate:",
"\tchance of 10%",
"\tadd 64 diamonds to the loot",
"\tsend \"You hit the jackpot at %event-location%!\""
)
.since("2.7")
.requiredPlugins("MC 1.16+");
}

if (Skript.classExists("io.papermc.paper.event.player.PlayerDeepSleepEvent")) {
Skript.registerEvent("Player Deep Sleep", SimpleEvent.class, PlayerDeepSleepEvent.class, "[player] deep sleep[ing]")
.description(
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.skriptlang.skript.bukkit.loottables;

import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import org.skriptlang.skript.bukkit.loottables.elements.expressions.ExprSecCreateLootContext;

/**
* The event used in the {@link ExprSecCreateLootContext} section.
*/
public class LootContextCreateEvent extends Event {

private final LootContextWrapper contextWrapper;

public LootContextCreateEvent(LootContextWrapper context) {
this.contextWrapper = context;
}

public LootContextWrapper getContextWrapper() {
return contextWrapper;
}

@Override
public @NotNull HandlerList getHandlers() {
throw new IllegalStateException();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package org.skriptlang.skript.bukkit.loottables;

import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.loot.LootContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Wrapper for a LootContext.Builder to allow easier creation of LootContexts.
*/
public class LootContextWrapper {

private @NotNull Location location;
private transient @Nullable LootContext cachedLootContext;
private @Nullable Player killer;
private @Nullable Entity entity;
private float luck;

/**
* Creates a new LootContextWrapper at the given location.
* @param location the location of the LootContext.
*/
public LootContextWrapper(@NotNull Location location) {
this.location = location;
}

/**
* Gets the LootContext from the wrapper.
* @return the LootContext.
*/
public LootContext getContext() {
if (cachedLootContext == null)
cachedLootContext = new LootContext.Builder(location)
.killer(killer)
.lootedEntity(entity)
.luck(luck)
.build();

return cachedLootContext;
}

/**
* Sets the location of the LootContext.
* @param location the location.
*/
public void setLocation(@NotNull Location location) {
this.location = location;
cachedLootContext = null;
}

/**
* Sets the killer of the LootContext.
* @param killer the killer.
*/
public void setKiller(@Nullable Player killer) {
this.killer = killer;
cachedLootContext = null;
}

/**
* Sets the entity of the LootContext.
* @param entity the entity.
*/
public void setEntity(@Nullable Entity entity) {
this.entity = entity;
cachedLootContext = null;
}

/**
* Sets the luck of the LootContext.
* @param luck the luck value.
*/
public void setLuck(float luck) {
this.luck = luck;
cachedLootContext = null;
}

/**
* Gets the location of the LootContext.
* @return the location.
*/
public Location getLocation() {
return location;
}

/**
* Gets the killer of the LootContext.
* @return the killer.
*/
public @Nullable Player getKiller() {
return killer;
}

/**
* Gets the entity of the LootContext.
* @return the entity.
*/
public @Nullable Entity getEntity() {
return entity;
}

/**
* Gets the luck of the LootContext.
* @return the luck value.
*/
public float getLuck() {
return luck;
}

}
Loading