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

EntityBlockStorage + Beehive #7316

Open
wants to merge 18 commits into
base: dev/feature
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package ch.njol.skript.conditions;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.lang.Condition;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.SyntaxStringBuilder;
import ch.njol.util.Kleenean;
import org.bukkit.block.Block;
import org.bukkit.block.EntityBlockStorage;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

@Name("Entity Storage Is Full")
@Description("Checks to see if the an entity block storage (i.e beehive) is full.")
@Examples({
"if the entity storage of {_beehive} is full:",
"\trelease the entity storage of {_beehive}"
})
@Since("INSERT VERSION")
public class CondEntityStorageIsFull extends Condition {

static {
Skript.registerCondition(CondEntityStorageIsFull.class, ConditionType.PROPERTY,
"[the] entity storage of %blocks% (is|are) full",
"%blocks%'[s] entity storage (is|are) full",
"[the] entity storage of %blocks% (isn't|is not|aren't|are not) full",
"%blocks%'[s] entity storage (isn't|is not|aren't|are not) full");
}

private Expression<Block> blocks;

@Override
public boolean init(Expression<?>[] exrps, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
setNegated(matchedPattern >= 2);
//noinspection unchecked
blocks = (Expression<Block>) exrps[0];
return true;
}

@Override
public boolean check(Event event) {
return blocks.check(event, block -> {
if (!(block.getState() instanceof EntityBlockStorage<?> blockStorage))
return false;
return blockStorage.isFull();
}, isNegated());
}

@Override
public String toString(@Nullable Event event, boolean debug) {
SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug);
builder.append("the entity storage of", blocks);
if (blocks.isSingle()) {
builder.append("is");
} else {
builder.append("are");
}
if (isNegated())
builder.append("not");
builder.append("full");
return builder.toString();
}

}
33 changes: 33 additions & 0 deletions src/main/java/ch/njol/skript/conditions/CondIsSedated.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ch.njol.skript.conditions;

import ch.njol.skript.conditions.base.PropertyCondition;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import org.bukkit.block.Beehive;
import org.bukkit.block.Block;

@Name("Beehive Is Sedated")
@Description("Checks if a beehive is sedated from a nearby campfire.")
@Examples("if {_beehive} is sedated:")
@Since("INSERT VERSION")
public class CondIsSedated extends PropertyCondition<Block> {

static {
PropertyCondition.register(CondIsSedated.class, PropertyType.BE, "sedated", "blocks");
}

@Override
public boolean check(Block block) {
if (!(block.getState() instanceof Beehive beehive))
return false;
return beehive.isSedated();
}

@Override
protected String getPropertyName() {
return "sedated";
}

}
51 changes: 51 additions & 0 deletions src/main/java/ch/njol/skript/effects/EffClearEntityStorage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package ch.njol.skript.effects;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.*;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.util.Kleenean;
import org.bukkit.block.Block;
import org.bukkit.block.EntityBlockStorage;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

@Name("Clear Entity Storage")
@Description("Clear the stored entities of an entity block storage (i.e. beehive).")
@Examples("clear the stored entities of {_beehive}")
@RequiredPlugins("Paper")
@Since("INSERT VERSION")
public class EffClearEntityStorage extends Effect {

static {
if (Skript.methodExists(EntityBlockStorage.class, "clearEntities"))
Skript.registerEffect(EffClearEntityStorage.class,
"(clear|empty) the (stored entities|entity storage) of %blocks%");
}

private Expression<Block> blocks;

@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
//noinspection unchecked
blocks = (Expression<Block>) exprs[0];
return true;
}

@Override
protected void execute(Event event) {
for (Block block : blocks.getArray(event)) {
if (!(block.getState() instanceof EntityBlockStorage<?> blockStorage))
continue;
blockStorage.clearEntities();
blockStorage.update(true, false);
}
}

@Override
public String toString(@Nullable Event event, boolean debug) {
return "clear the stored entities of " + blocks.toString(event, debug);
}

}
100 changes: 100 additions & 0 deletions src/main/java/ch/njol/skript/effects/EffInsertEntityStorage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package ch.njol.skript.effects;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.*;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.util.Kleenean;
import org.bukkit.block.Beehive;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.EntityBlockStorage;
import org.bukkit.entity.Bee;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Map;

@Name("Insert Entity Storage")
@Description({
"Add an entity into the entity storage of a block (e.g. beehive).",
"The entity must be of the right type for the block (e.g. bee for beehive).",
"Due to unstable behavior on older versions, adding entities to an entity storage requires Minecraft version 1.21+."
})
@Examples("add last spawned bee into the entity storage of {_beehive}")
@RequiredPlugins("Minecraft 1.21+")
@Since("INSERT VERSION")
public class EffInsertEntityStorage extends Effect {

/*
Minecraft versions 1.19.4 -> 1.20.6 have unstable behavior.
Entity is either not added, or added but still exists.
Releasing entities on these versions is also unstable.
Either entities are not released or are released and not clearing the stored entities.
*/

private static final Map<Class<? extends BlockState>, Class<? extends Entity>> STORAGES = new HashMap<>();

static {
if (Skript.isRunningMinecraft(1, 21, 0)) {
Skript.registerEffect(EffInsertEntityStorage.class,
"(add|insert) %livingentities% [in[ ]]to [the] (stored entities|entity storage) of %block%");
STORAGES.put(Beehive.class, Bee.class);
}
}

private Expression<? extends Entity> entities;
private Expression<Block> block;

@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
//noinspection unchecked
entities = (Expression<? extends Entity>) exprs[0];
//noinspection unchecked
block = (Expression<Block>) exprs[1];
return true;
}

@Override
protected void execute(Event event) {
Block block = this.block.getSingle(event);
if (block == null || !(block.getState() instanceof EntityBlockStorage<?> blockStorage))
return;
Class<? extends Entity> entityClass = getEntityClass(blockStorage);
if (entityClass == null)
return;
addEntities(entityClass, blockStorage, this.entities.getArray(event));
}

private <T extends EntityBlockStorage<R>, R extends Entity> void addEntities(Class<R> entityClass, BlockState blockState, Entity[] entities) {
//noinspection unchecked
T typedStorage = (T) blockState;
for (Entity entity : entities) {
if (!entityClass.isInstance(entity))
continue;
if (typedStorage.getEntityCount() >= typedStorage.getMaxEntities())
break;
//noinspection unchecked
R typedEntity = (R) entity;
typedStorage.addEntity(typedEntity);
}
typedStorage.update(true, false);
}

private @Nullable Class<? extends Entity> getEntityClass(BlockState blockState) {
for (Class<? extends BlockState> stateClass : STORAGES.keySet()) {
if (stateClass.isInstance(blockState))
return STORAGES.get(stateClass);
}
return null;
}

@Override
public String toString(@Nullable Event event, boolean debug) {
return "add " + entities.toString(event, debug) + " into the entity storage of " + block.toString(event, debug);
}

}
93 changes: 93 additions & 0 deletions src/main/java/ch/njol/skript/effects/EffReleaseEntityStorage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package ch.njol.skript.effects;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.*;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.SyntaxStringBuilder;
import ch.njol.skript.util.Timespan;
import ch.njol.skript.util.Timespan.TimePeriod;
import ch.njol.util.Kleenean;
import org.bukkit.block.Block;
import org.bukkit.block.EntityBlockStorage;
import org.bukkit.entity.Bee;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

import java.util.List;

@Name("Release From Entity Storage")
@Description({
"Releases the stored entities in an entity block storage (i.e. beehive).",
"When using beehives, providing a timespan will prevent the released bees from re-entering the beehive for that amount of time.",
"Due to unstable behaviour on older versions, this effect requires Minecraft version 1.21+."
})
@Examples({
"release the stored entities of {_beehive}",
"release the entity storage of {_hive} for 5 seconds"
})
@RequiredPlugins("Minecraft 1.21")
@Since("INSERT VERSION")
public class EffReleaseEntityStorage extends Effect {

/*
Minecraft versions 1.19.4 -> 1.20.6 have unstable behavior.
Either entities are not released or are released and not clearing the stored entities.
Adding entities into EntityBlockStorage's are also unstable.
Entities are either not added, or added but still exist.
*/

static {
if (Skript.isRunningMinecraft(1, 21, 0)) {
Skript.registerEffect(EffReleaseEntityStorage.class,
"(release|evict) [the] (stored entities|entity storage) of %blocks% [for %-timespan%]");
TheAbsolutionism marked this conversation as resolved.
Show resolved Hide resolved
}
}

private Expression<Block> blocks;
private @Nullable Expression<Timespan> timespan;

@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
//noinspection unchecked
blocks = (Expression<Block>) exprs[0];
if (exprs[1] != null)
//noinspection unchecked
timespan = (Expression<Timespan>) exprs[1];
return true;
}

@Override
protected void execute(Event event) {
Integer ticks = null;
if (timespan != null) {
Timespan time = timespan.getSingle(event);
if (time != null)
ticks = (int) time.getAs(TimePeriod.TICK);
}
for (Block block : blocks.getArray(event)) {
if (!(block.getState() instanceof EntityBlockStorage<?> blockStorage))
continue;
List<? extends Entity> released = blockStorage.releaseEntities();
if (ticks != null) {
for (Entity entity : released) {
if (entity instanceof Bee bee) {
bee.setCannotEnterHiveTicks(ticks);
}
}
}
}
}

@Override
public String toString(@Nullable Event event, boolean debug) {
SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug);
builder.append("release the stored entities of", blocks);
if (timespan != null)
builder.append("for", timespan);
return builder.toString();
}

}
Loading
Loading