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
Show file tree
Hide file tree
Changes from all 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
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
18 changes: 0 additions & 18 deletions src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
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
Expand Up @@ -602,21 +602,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(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.skriptlang.skript.bukkit.loottables;

import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
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 HandlerList getHandlers() {
throw new UnsupportedOperationException();
}

}
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;
}

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

import ch.njol.skript.Skript;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.classes.Parser;
import ch.njol.skript.expressions.base.EventValueExpression;
import ch.njol.skript.lang.ParseContext;
import ch.njol.skript.lang.util.SimpleEvent;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.registrations.EventValues;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Entity;
import org.bukkit.event.world.LootGenerateEvent;
import org.bukkit.loot.LootContext;
import org.bukkit.loot.LootTable;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;

public class LootTableModule {

public static void load() throws IOException {

// --- CLASSES --- //

Classes.registerClass(new ClassInfo<>(LootTable.class, "loottable")
.user("loot ?tables?")
.name("Loot Table")
.description(
"Loot tables represent what items should be in naturally generated containers, "
+ "what items should be dropped when killing a mob, or what items can be fished.",
"You can find more information about this in https://minecraft.wiki/w/Loot_table"
)
.since("INSERT VERSION")
.parser(new Parser<>() {
@Override
public @Nullable LootTable parse(String key, ParseContext context) {
NamespacedKey namespacedKey = NamespacedKey.fromString(key);
if (namespacedKey == null)
return null;
return Bukkit.getLootTable(namespacedKey);
}

@Override
public String toString(LootTable o, int flags) {
return "loot table \"" + o.getKey() + '\"';
}

@Override
public String toVariableNameString(LootTable o) {
return "loot table:" + o.getKey();
}
})
);

Classes.registerClass(new ClassInfo<>(LootContext.class, "lootcontext")
.user("loot ?contexts?")
.name("Loot Context")
.description(
"Represents additional information a loot table can use to modify its generated loot.",
"",
"Some loot tables will require some values (i.e. looter, location, looted entity) "
+ "in a loot context when generating loot whereas others may not.",
"For example, the loot table of a simple dungeon chest will only require a location, "
+ "whereas the loot table of a cow will require a looting player, looted entity, and location.",
"You can find more information about this in https://minecraft.wiki/w/Loot_context"
)
.since("INSERT VERSION")
.defaultExpression(new EventValueExpression<>(LootContext.class))
.parser(new Parser<>() {
@Override
public boolean canParse(ParseContext context) {
return false;
}

@Override
public String toString(LootContext context, int flags) {
StringBuilder builder = new StringBuilder("loot context at ")
.append(Classes.toString(context.getLocation()));

if (context.getLootedEntity() != null)
builder.append(" with entity ").append(Classes.toString(context.getLootedEntity()));
if (context.getKiller() != null)
builder.append(" with killer ").append(Classes.toString(context.getKiller()));
if (context.getLuck() != 0)
builder.append(" with luck ").append(context.getLuck());

return builder.toString();
}

@Override
public String toVariableNameString(LootContext context) {
return "loot context:" + context.hashCode();
}
})
);

Skript.getAddonInstance().loadClasses("org.skriptlang.skript.bukkit.loottables", "elements");

// --- SIMPLE EVENTS --- //

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+");

// --- EVENT VALUES --- //

// LootGenerateEvent
EventValues.registerEventValue(LootGenerateEvent.class, Entity.class, LootGenerateEvent::getEntity);
EventValues.registerEventValue(LootGenerateEvent.class, Location.class, event -> event.getLootContext().getLocation());
EventValues.registerEventValue(LootGenerateEvent.class, LootTable.class, LootGenerateEvent::getLootTable);
EventValues.registerEventValue(LootGenerateEvent.class, LootContext.class, LootGenerateEvent::getLootContext);
}

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

import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.loot.LootTable;
import org.bukkit.loot.Lootable;

/**
* Utility class for loot tables.
*/
public class LootTableUtils {

/**
* * Checks whether a block or entity is an instance of {@link Lootable}. This is done because a block is not an instance of Lootable, but a block state is.
* @param object the object to check.
* @return whether the object is lootable.
*/
public static boolean isLootable(Object object) {
if (object instanceof Block block)
object = block.getState();
return object instanceof Lootable;
}

/**
* Gets the Lootable instance of an object. You should call {@link #isLootable(Object)} before calling this method.
* @param object the object to get the Lootable instance of.
* @return the Lootable instance of the object.
*/
public static Lootable getAsLootable(Object object) {
if (object instanceof Block block)
object = block.getState();
if (object instanceof Lootable lootable)
return lootable;
return null;
}

/**
* Gets the loot table of an object. You should call {@link #isLootable(Object)} before calling this method.
* @param object the object to get the loot table of.
* @return returns the LootTable of the object.
*/
public static LootTable getLootTable(Object object) {
return getAsLootable(object).getLootTable();
}

/**
* Updates the state of a Lootable. This is done because setting the LootTable or seed of a BlockState changes the NBT value, but is never updated.
* @param lootable the Lootable to update the state of.
*/
public static void updateState(Lootable lootable) {
if (lootable instanceof BlockState blockState)
blockState.update(true, false);
}

}
Loading
Loading