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,70 @@
package ch.njol.skript.bukkitutil;

import org.bukkit.block.Beehive;
import org.bukkit.block.BlockState;
import org.bukkit.block.EntityBlockStorage;
import org.bukkit.entity.Bee;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.Nullable;

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

public class EntityBlockStorageUtils {

// Future proofing for any EntityBlockStorage added later on
// Any new EntityBlockStorage extensions should only need to be added here

public enum EntityBlockStorageType {

ENTITY_STORAGE("entity block storage"),
BEEHIVE(Beehive.class, Bee.class, "beehive storage");

private Class<? extends EntityBlockStorage<?>> entityStorageClass = null;
private Class<? extends Entity> entityClass = null;
private final String name;
private boolean superType = false;

EntityBlockStorageType(Class<? extends EntityBlockStorage<?>> entityStorageClass, Class<? extends Entity> entityClass, String name) {
this.entityStorageClass = entityStorageClass;
this.entityClass = entityClass;
this.name = name;
}

EntityBlockStorageType(String name) {
superType = true;
this.name = name;
}

public @Nullable Class<? extends EntityBlockStorage<?>> getEntityStorageClass() {
return entityStorageClass;
}

public @Nullable Class<? extends Entity> getEntityClass() {
return entityClass;
}

public String getName() {
return name;
}

public boolean isSuperType() {
return superType;
}

}

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

static {
for (EntityBlockStorageType type : EntityBlockStorageType.values()) {
if (!type.superType)
blockStateToEntityStorage.put(type.entityStorageClass, type);
}
}

public static @Nullable EntityBlockStorageType getEntityBlockStorageType(BlockState blockState) {
return blockStateToEntityStorage.get(blockState.getClass());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package ch.njol.skript.conditions;

import ch.njol.skript.Skript;
import ch.njol.skript.bukkitutil.EntityBlockStorageUtils.EntityBlockStorageType;
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 an entity block storage (i.e beehive) is full.",
"Using a specific block storage type will restrict the blocks provided to match the type.",
"Any blocks provided not matching the block storage type will fail the condition."
})
@Examples({
"if the beehive storage of {_beehive} is full:",
"release the beehive storage of {_beehive}"
TheAbsolutionism marked this conversation as resolved.
Show resolved Hide resolved
})
@Since("INSERT VERSION")
public class CondEntityStorageIsFull extends Condition {

// Future proofing for any EntityBlockStorage added later on

private static final EntityBlockStorageType[] ENTITY_BLOCK_STORAGE_TYPES = EntityBlockStorageType.values();

static {
String[] patterns = new String[ENTITY_BLOCK_STORAGE_TYPES.length * 2];
for (EntityBlockStorageType type : ENTITY_BLOCK_STORAGE_TYPES) {
patterns[type.ordinal() * 2] = "[the] " + type.getName() + " of %blocks% (is|are) full";
patterns[(type.ordinal() * 2) + 1] = "[the] " + type.getName() + " of %blocks% (isn't|is not|aren't|are not) full";
}
Skript.registerCondition(CondEntityStorageIsFull.class, ConditionType.PROPERTY, patterns);
}

private EntityBlockStorageType storageType;
private Expression<Block> blocks;
private boolean checkFull;

@Override
public boolean init(Expression<?>[] exrps, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
storageType = ENTITY_BLOCK_STORAGE_TYPES[matchedPattern / 2];
checkFull = matchedPattern % 2 == 0;
//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;
if (!storageType.isSuperType() && !storageType.getEntityStorageClass().isInstance(blockStorage))
return false;
return blockStorage.isFull() == checkFull;
});
}

@Override
public String toString(@Nullable Event event, boolean debug) {
SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug);
builder.append("the", storageType.getName(), "of", blocks);
if (blocks.isSingle()) {
builder.append("is");
} else {
builder.append("are");
}
if (!checkFull)
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("Is Sedated")
TheAbsolutionism marked this conversation as resolved.
Show resolved Hide resolved
@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";
}

}
87 changes: 87 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,87 @@
package ch.njol.skript.effects;

import ch.njol.skript.Skript;
import ch.njol.skript.bukkitutil.EntityBlockStorageUtils.EntityBlockStorageType;
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.Effect;
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("Release Entity Storage")
TheAbsolutionism marked this conversation as resolved.
Show resolved Hide resolved
@Description({
"Release the entities stored in an entity block storage (i.e. beehive).",
TheAbsolutionism marked this conversation as resolved.
Show resolved Hide resolved
"Using a specific block storage type will restrict the blocks provided to match the type.",
"Please note that releasing entities will effectively duplicate the entities.",
"The 'and clear' requires a Paper Server."
})
@Examples({
"release the beehive storage of {_beehive}",
"release and clear the beehive storage stored entities of {_hive}"
})
@Since("INSERT VERSION")
public class EffReleaseEntityStorage extends Effect {

// Future proofing for any EntityBlockStorage added later on

private static final boolean SUPPORTS_CLEAR = Skript.methodExists(EntityBlockStorage.class, "clearEntities");
private static final EntityBlockStorageType[] ENTITY_BLOCK_STORAGE_TYPES = EntityBlockStorageType.values();

static {
String[] patterns = new String[ENTITY_BLOCK_STORAGE_TYPES.length];
for (EntityBlockStorageType type : ENTITY_BLOCK_STORAGE_TYPES) {
patterns[type.ordinal()] = "release [clear:and (clear|empty)] [the] " + type.getName() + " [stored entities] of %blocks%";
}
Skript.registerEffect(EffReleaseEntityStorage.class, patterns);
}

private EntityBlockStorageType storageType;
private Expression<Block> blocks;
private boolean clear;

@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
storageType = ENTITY_BLOCK_STORAGE_TYPES[matchedPattern];
//noinspection unchecked
blocks = (Expression<Block>) exprs[0];
clear = parseResult.hasTag("clear");
if (clear && !SUPPORTS_CLEAR) {
Skript.error("You can only use 'and clear' on a Paper server.");
return false;
}
return true;
}

@Override
protected void execute(Event event) {
for (Block block : blocks.getArray(event)) {
if (!(block.getState() instanceof EntityBlockStorage<?> blockStorage))
continue;
if (!storageType.isSuperType() && !storageType.getEntityStorageClass().isInstance(blockStorage))
continue;
blockStorage.releaseEntities();
if (clear)
blockStorage.clearEntities();
TheAbsolutionism marked this conversation as resolved.
Show resolved Hide resolved
blockStorage.update(true, false);
}
}

@Override
public String toString(@Nullable Event event, boolean debug) {
SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug);
builder.append("release");
if (clear)
builder.append("and clear");
builder.append("the", storageType.getName(), "stored entities of", blocks);
return builder.toString();
}

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

import ch.njol.skript.classes.Changer.ChangeMode;
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.expressions.base.SimplePropertyExpression;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.Location;
import org.bukkit.block.Beehive;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

@Name("Beehive Flower Target")
@Description("The flower a beehive has selected to pollinate from.")
@Examples({
"set the flower target of {_beehive} to block at location(0, 0, 0)",
"clear the flower target of {_beehive}"
})
@Since("INSERT VERSION")
public class ExprBeehiveFlower extends SimplePropertyExpression<Block, Block> {
TheAbsolutionism marked this conversation as resolved.
Show resolved Hide resolved

static {
registerDefault(ExprBeehiveFlower.class, Block.class, "flower target", "blocks");
}

@Override
public @Nullable Block convert(Block block) {
if (!(block.getState() instanceof Beehive beehive))
return null;
Location location = beehive.getFlower();
return location != null ? location.getBlock() : null;
}

@Override
public Class<?> @Nullable [] acceptChange(ChangeMode mode) {
if (mode == ChangeMode.SET || mode == ChangeMode.DELETE)
return CollectionUtils.array(Location.class, Block.class);
return null;
}

@Override
public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
Location location = null;
if (delta != null) {
if (delta[0] instanceof Location loc) {
location = loc;
} else if (delta[0] instanceof Block block) {
location = block.getLocation();
}
}
for (Block block : getExpr().getArray(event)) {
if (!(block.getState() instanceof Beehive beehive))
continue;
beehive.setFlower(location);
beehive.update(true, false);
}
}

@Override
public Class<Block> getReturnType() {
return Block.class;
}

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

}
Loading
Loading