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

Add block explode event & fix exploded blocks change method #3990

Closed
Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
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
77 changes: 77 additions & 0 deletions src/main/java/ch/njol/skript/events/EvtExplode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* This file is part of Skript.
*
* Skript is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Skript is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Skript. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright Peter Güttinger, SkriptLang team and contributors
*/
package ch.njol.skript.events;

import ch.njol.skript.Skript;
import ch.njol.skript.lang.Literal;
import ch.njol.skript.lang.SkriptEvent;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.event.Event;
import org.bukkit.event.block.BlockExplodeEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.eclipse.jdt.annotation.Nullable;

@SuppressWarnings("unchecked")
public class EvtExplode extends SkriptEvent {
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved

private final static int ENTITY = 1, BLOCK = 2, ANY = ENTITY | BLOCK;
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved

static {
Class<? extends Event>[] eventTypes = CollectionUtils.array(EntityExplodeEvent.class, BlockExplodeEvent.class);

Skript.registerEvent("entity/block explode", EvtExplode.class, eventTypes, "[(1¦entity|2¦block)] explo(d(e|ing)|sion)")
.description(
"Called when an entity (a primed TNT or a creeper) explodes " +
"OR Called when a block explodes. (Also triggered by <a href='effects.html#EffExplosion'>create explosion effect</a>)" +
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
" " +
"If explosion type is specified only that type of explosion will trigger the event.")
.examples("on explode:",
"\tbroadcast \"a(n) %explosion type% just exploded.\"",
"on block explode:",

"\tbroadcast \"A block just exploded\"",
"on entity explode:",

"\tbroadcast \"An entity just exploded\"")
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
.since("1.0, INSERT VERSION (block explode)");
}

@Nullable
private int type;

@Override
@SuppressWarnings("null")
public boolean init(final Literal<?>[] args, final int matchedPattern, final ParseResult parser) {
type = parser.mark == 0 ? ANY : parser.mark;
return true;
}

@Override
@SuppressWarnings("null")
public boolean check(final Event e) {
return type == ENTITY ? e instanceof EntityExplodeEvent : (type == BLOCK ? e instanceof BlockExplodeEvent : true);
}

@Override
public String toString(final @Nullable Event e, final boolean debug) {
return (type == ENTITY ? "entity " : (type == BLOCK ? "block " : "")) + "explode";
}

}
6 changes: 0 additions & 6 deletions src/main/java/ch/njol/skript/events/SimpleEvents.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@
import org.bukkit.event.entity.CreeperPowerEvent;
import org.bukkit.event.entity.EntityBreakDoorEvent;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityPortalEnterEvent;
import org.bukkit.event.entity.EntityPortalEvent;
import org.bukkit.event.entity.EntityPortalExitEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityResurrectEvent;
import org.bukkit.event.entity.EntityTameEvent;
Expand Down Expand Up @@ -193,10 +191,6 @@ public class SimpleEvents {
.description("Called when an entity is set on fire, e.g. by fire or lava, a fireball, or by standing in direct sunlight (zombies, skeletons).")
.examples("on combust:")
.since("1.0");
Skript.registerEvent("Explode", SimpleEvent.class, EntityExplodeEvent.class, "explo(d(e|ing)|sion)")
.description("Called when an entity (a primed TNT or a creeper) explodes.")
.examples("on explosion:")
.since("1.0");
// Skript.registerEvent(SimpleEvent.class, EntityInteractEvent.class, "interact");// = entity interacts with block, e.g. endermen?; player -> PlayerInteractEvent // likely tripwires, pressure plates, etc.
Skript.registerEvent("Portal Enter", SimpleEvent.class, EntityPortalEnterEvent.class, "portal enter[ing]", "entering [a] portal")
.description("Called when an entity enters a nether portal or an end portal. Please note that this event will be fired many times for a nether portal.")
Expand Down
127 changes: 116 additions & 11 deletions src/main/java/ch/njol/skript/expressions/ExprExplodedBlocks.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,19 @@
*/
package ch.njol.skript.expressions;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import ch.njol.skript.aliases.ItemType;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.block.BlockExplodeEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.eclipse.jdt.annotation.Nullable;
import ch.njol.skript.classes.Changer.ChangeMode;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.Description;
Expand All @@ -33,37 +40,135 @@
import ch.njol.skript.doc.Since;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptParser;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.util.Kleenean;

@Name("Exploded Blocks")
@Description("Get all the blocks that were destroyed in an explode event")
@Examples({"on explode:",
@Description("Get all the blocks that were destroyed in an entity/block explode event (Can be set/removed from/deleted/added to)")
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
@Examples({
"on block explode:",
"\tadd exploded blocks to {_exploded-blocks::*}",
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
"\t",
"\tloop exploded blocks:",
"\t\tadd loop-block to {exploded::blocks::*}"})
"\t\tif loop-block is sand:",
"\t\t\tset loop-block to stone",
"\t",
"\tset exploded blocks to blocks in radius 3 around event-location # this will clear exploded blocks and set it to the specified blocks",
"\tremove all chests from exploded blocks",
"\tremove 3 stone from exploded blocks # will remove only 3 stone blocks",
"\tremove stone from exploded blocks # will remove all stones blocks - 'any' and 'all' will do the same",
"\tadd blocks in radius 3 around event-location to exploded blocks",
"\tdelete exploded blocks # will clear exploded blocks",
"\t",
"on entity explode:",
"\tremove all stone from exploded blocks",
"\t",
"on explode:",
"\tremove all stone from exploded blocks"})
@Events("explode")
@Since("2.5")
@Since("2.5, INSERT VERSION (changing the list)")
public class ExprExplodedBlocks extends SimpleExpression<Block> {

static {
Skript.registerExpression(ExprExplodedBlocks.class, Block.class, ExpressionType.COMBINED, "[the] exploded blocks");
Skript.registerExpression(ExprExplodedBlocks.class, Block.class, ExpressionType.SIMPLE, "[the] exploded blocks");
}

@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
if (!getParser().isCurrentEvent(EntityExplodeEvent.class)) {
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
if (!getParser().isCurrentEvent(BlockExplodeEvent.class, EntityExplodeEvent.class)) {
Skript.error("Exploded blocks can only be retrieved from an explode event.");
return false;
}
return true;
}

@Nullable
@Override
@Nullable
protected Block[] get(Event e) {
List<Block> blockList = ((EntityExplodeEvent) e).blockList();
return blockList.toArray(new Block[blockList.size()]);
return getBlocks(e).toArray(new Block[0]);
}

@Override
@Nullable
public Iterator<? extends Block> iterator(Event e) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is overriding iterator necessary here?

List<Block> blocks = getBlocks(e);
return new ArrayList(blocks).iterator();
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
@Nullable
public Class<?>[] acceptChange(final ChangeMode mode) {
switch (mode) {
case ADD:
case SET:
case DELETE:
return CollectionUtils.array(Block[].class);
case REMOVE:
case REMOVE_ALL:
return CollectionUtils.array(Block[].class, ItemType[].class);
case RESET:
default:
return null;
}
}

@Override
public void change(Event e, final @Nullable Object[] delta, final ChangeMode mode) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public void change(Event e, final @Nullable Object[] delta, final ChangeMode mode) {
public void change(Event e, @Nullable Object[] delta, ChangeMode mode) {

List<Block> blocks = getBlocks(e);

switch (mode) {
case DELETE:
case SET:
case ADD:
if (mode != ChangeMode.ADD)
blocks.clear();

if (mode != ChangeMode.DELETE) {
assert delta != null;
for (Object o : delta) {
if (o instanceof ItemType)
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
continue;

if (((Block) o).getType() != Material.AIR) // Performance
blocks.add((Block) o);
}
}
break;

case REMOVE:
case REMOVE_ALL: // ItemType here will allow `remove [all] %itemtypes% from exploded blocks` to remove all/specific amount of specific block type that matches an itemtype, a shortcut for looping
assert delta != null;
int amountRemoved = 0; // Remove X alias

for (Object o : delta) {
if (o instanceof Block) {
blocks.remove((Block) o); // no need to check whether they are equals, since blocks are only passed by reference
} else if (o instanceof ItemType) {
ItemType item = ((ItemType) o);
int amount = item.getInternalAmount(); // -1 when using 'all' or 'any' of alias

if (amount == -1 || mode == ChangeMode.REMOVE_ALL) { // all %itemtype% OR REMOVE_ALL
blocks.removeIf(item::isOfType);
break;
} else if (amount > 0)
for (Block b : new ArrayList<>(blocks)) {
if (amountRemoved >= amount)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen when you use remove 5 dirt and 2 stone from exploded blocks? Looks like it'll not remove any stone, but could be wrong

break;
else if (item.isOfType(b)) {
blocks.remove(b);
amountRemoved++; // only ++ if a matched item was removed
}
}
}
}
break;
}
}


private static List<Block> getBlocks(Event e) {
return e instanceof EntityExplodeEvent ? ((EntityExplodeEvent) e).blockList() : ((BlockExplodeEvent) e).blockList();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package ch.njol.skript.expressions;

import org.bukkit.event.Event;
import org.bukkit.event.block.BlockExplodeEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.eclipse.jdt.annotation.Nullable;

Expand Down Expand Up @@ -53,11 +54,11 @@ public class ExprExplosionBlockYield extends SimpleExpression<Number> {
"[the] percentage of blocks dropped"
);
}

@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
if (!getParser().isCurrentEvent(EntityExplodeEvent.class)) {
Skript.error("The 'explosion block yield' is only usable in an explosion event", ErrorQuality.SEMANTIC_ERROR);
if (!getParser().isCurrentEvent(BlockExplodeEvent.class, EntityExplodeEvent.class)) {
Skript.error("Explosion block yield can only be retrieved from an explode event.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Skript.error("Explosion block yield can only be retrieved from an explode event.");
Skript.error("Explosion block yield can only be retrieved from an explode event");

return false;
}
return true;
Expand All @@ -66,7 +67,7 @@ public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelaye
@Override
@Nullable
protected Number[] get(Event e) {
return new Number[]{((EntityExplodeEvent) e).getYield()};
return new Number[]{ typeGetYield(e) };
}

@Override
Expand All @@ -88,32 +89,48 @@ public void change(final Event event, final @Nullable Object[] delta, final Chan
float n = delta == null ? 0 : ((Number) delta[0]).floatValue();
if (n < 0) // Yield can't be negative
return;
EntityExplodeEvent e = (EntityExplodeEvent) event;
// Yield can be a value from 0 to 1
switch (mode) {
case SET:
e.setYield(n);
typeSetYield(event, n);
break;
case ADD:
float add = e.getYield() + n;
float add = typeGetYield(event) + n;
if (add < 0)
return;
e.setYield(add);
typeSetYield(event, add);
break;
case REMOVE:
float subtract = e.getYield() - n;
float subtract = typeGetYield(event) - n;
if (subtract < 0)
return;
e.setYield(subtract);
typeSetYield(event, subtract);
break;
case DELETE:
e.setYield(0);
typeSetYield(event, 0);
break;
default:
assert false;
}
}

private float typeGetYield(Event e) {
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
if (e instanceof EntityExplodeEvent) {
return ((EntityExplodeEvent) e).getYield();
} else {
return ((BlockExplodeEvent) e).getYield();
}
}

private void typeSetYield(Event e, float yield) {
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
if (e instanceof EntityExplodeEvent) {
((EntityExplodeEvent) e).setYield(yield);
} else {
((BlockExplodeEvent) e).setYield(yield);
}
}

@Override
public boolean isSingle() {
return true;
Expand Down
Loading