Skip to content

Improve itemframes #7749

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

Open
wants to merge 8 commits into
base: dev/feature
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
14 changes: 14 additions & 0 deletions src/main/java/ch/njol/skript/classes/data/BukkitClasses.java
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,20 @@ public String toVariableNameString(WorldBorder border) {
.changer(DefaultChangers.entityChanger)
);

Classes.registerClass(new ClassInfo<>(ItemFrame.class, "itemframe")
.user("item ?frames?")
.name("Item Frame")
.description("Represents the itemframe entity. This classinfo is used to manipulate settings of itemframes in syntaxes.")
.since("INSERT VERSION")
.defaultExpression(new EventValueExpression<>(ItemFrame.class)));

Classes.registerClass(new EnumClassInfo<>(Rotation.class, "rotation", "rotations")
.user("rotations?")
.name("Rotation")
.description(
"Specify a rotation based orientation, like that on a clock. Used in item frames.",
"It represents how something is viewed, as opposed to cardinal directions.")
.since("INSERT VERSION"));
}

}
15 changes: 8 additions & 7 deletions src/main/java/ch/njol/skript/classes/data/SkriptClasses.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
package ch.njol.skript.classes.data;

import java.io.StreamCorruptedException;
import java.util.Iterator;
import java.util.Locale;
import java.util.regex.Pattern;

import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import ch.njol.skript.ScriptLoader;
import ch.njol.skript.Skript;
import ch.njol.skript.aliases.Aliases;
Expand All @@ -25,23 +33,16 @@
import ch.njol.skript.util.visual.VisualEffect;
import ch.njol.skript.util.visual.VisualEffects;
import ch.njol.yggdrasil.Fields;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import org.skriptlang.skript.lang.script.Script;
import org.skriptlang.skript.lang.util.SkriptQueue;
import org.skriptlang.skript.util.Executable;

import java.io.File;
import java.io.NotSerializableException;
import java.io.StreamCorruptedException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

@SuppressWarnings("rawtypes")
public class SkriptClasses {
Expand Down
115 changes: 115 additions & 0 deletions src/main/java/ch/njol/skript/effects/EffRotate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package ch.njol.skript.effects;

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

import org.bukkit.Rotation;
import org.bukkit.entity.ItemFrame;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

import ch.njol.skript.Skript;
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.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.Literal;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.util.Kleenean;

@Name("Rotate")
@Description("Rotate rotations or itemframes an amount of times based on the provided rotation.")
@Examples({
"rotate the event-item frame clockwise 2 times",
"rotate the event-item frame by 225 degrees"
})
@Since("INSERT VERSION")
public class EffRotate extends Effect {

static {
Skript.registerEffect(EffRotate.class, "rotate %~rotations% [:counter] clockwise %*number% times");
Skript.registerEffect(EffRotate.class, "rotate %itemframes% [by] %rotation%");
}

private @Nullable Expression<ItemFrame> itemFrames;
private Expression<Rotation> rotations;
private boolean counter;
private int amount;

@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
rotations = (Expression<Rotation>) exprs[matchedPattern ^ 0];
if (matchedPattern == 0) {
amount = Optional.ofNullable(((Literal<Number>) exprs[1]))
.map(Literal::getSingle)
.map(Number::intValue)
.orElse(1);
} else {
itemFrames = (Expression<ItemFrame>) exprs[0];
}
counter = parseResult.hasTag("counter");
return true;
}

@Override
protected void execute(Event event) {
if (itemFrames != null) {
Rotation rotation = rotations.getOptionalSingle(event).orElse(Rotation.NONE);
if (rotation == Rotation.NONE)
return;
itemFrames.stream(event).forEach(itemFrame ->
itemFrame.setRotation(rotate(itemFrame.getRotation(), rotation)));
return;
}
rotations.change(event, rotations.stream(event).map(this::rotate).toArray(Rotation[]::new), ChangeMode.SET);
}

/**
* The amount of times to rotate clockwise to get to the matched degree.
*/
private static final Map<Rotation, Integer> order = new HashMap<>();

static {
order.put(Rotation.CLOCKWISE_45, 1);
order.put(Rotation.CLOCKWISE, 2);
order.put(Rotation.CLOCKWISE_135, 3);
order.put(Rotation.FLIPPED, 4);
order.put(Rotation.FLIPPED_45, 5);
order.put(Rotation.COUNTER_CLOCKWISE, 6);
order.put(Rotation.COUNTER_CLOCKWISE_45, 7);
}

private Rotation rotate(Rotation relative, Rotation rotation) {
for (int i = 0; i < order.get(relative); i++)
rotation.rotateClockwise();
return rotation;
}

private Rotation rotate(Rotation rotation) {
for (int i = 0; i < amount; i++) {
if (counter) {
rotation.rotateCounterClockwise();
} else {
rotation.rotateClockwise();
}
}
return rotation;
}

@Override
public String toString(@Nullable Event event, boolean debug) {
String string;
if (itemFrames != null) {
string = "rotate " + itemFrames.toString(event, debug) + " " + rotations.toString(event, debug);
} else {
string = "rotate " + rotations.toString(event, debug) + (counter ? " counter " : "") + " clockwise";
}
return string + " " + amount + " time" + (amount <= 1 ? "" : "s");
Comment on lines +106 to +112
Copy link
Contributor

Choose a reason for hiding this comment

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

SSB?

}

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

import org.bukkit.Rotation;
import org.bukkit.entity.ItemFrame;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;

import ch.njol.skript.aliases.ItemType;
import ch.njol.skript.lang.Literal;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.localization.Noun;
import ch.njol.skript.registrations.Classes;

public class ItemFrameData extends EntityData<ItemFrame> {

static {
EntityData.register(ItemFrameData.class, "item frame", ItemFrame.class, "item frame");
}

private @Nullable ItemType type;

private Rotation rotation = Rotation.NONE;

public ItemFrameData() {}

public ItemFrameData(@Nullable ItemType type, @Nullable Rotation rotation) {
this.rotation = rotation;
this.type = type;
}

@Override
protected boolean init(Literal<?>[] exprs, int matchedPattern, ParseResult parseResult) {
if (exprs[0] != null)
type = (ItemType) exprs[0].getSingle();
if (exprs[1] != null)
rotation = (Rotation) exprs[1].getSingle();
return true;
}

@Override
protected boolean init(@Nullable Class<? extends ItemFrame> entityClass, @Nullable ItemFrame itemframe) {
if (itemframe != null) {
ItemStack item = itemframe.getItem();
type = new ItemType(item);
rotation = itemframe.getRotation();
}
return true;
}

@Override
protected boolean match(ItemFrame itemframe) {
if (type == null)
return true;
return type.isOfType(itemframe.getItem()) && itemframe.getRotation() == rotation;
}

@Override
public void set(ItemFrame itemframe) {
assert type != null;
ItemStack item = type.getItem().getRandom();
if (item != null)
itemframe.setItem(item);
itemframe.setRotation(rotation);
}

@Override
public boolean isSupertypeOf(EntityData<?> entityData) {
if (!(entityData instanceof ItemFrameData))
return false;
ItemFrameData itemFrameData = (ItemFrameData) entityData;
if (type != null)
return itemFrameData.type != null && type.equals(itemFrameData.type) && rotation == itemFrameData.rotation;
Comment on lines +68 to +72
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if (!(entityData instanceof ItemFrameData))
return false;
ItemFrameData itemFrameData = (ItemFrameData) entityData;
if (type != null)
return itemFrameData.type != null && type.equals(itemFrameData.type) && rotation == itemFrameData.rotation;
if (!(entityData instanceof ItemFrameData other))
return false;
if (type != null)
return other.type != null && type.equals(other.type) && rotation == other.rotation;

return true;
}

@Override
public Class<? extends ItemFrame> getType() {
return ItemFrame.class;
}

@Override
public EntityData<?> getSuperType() {
return new ItemFrameData(type, rotation);
}

@Override
public String toString(int flags) {
if (type == null)
return super.toString(flags);
StringBuilder builder = new StringBuilder();
builder.append(Noun.getArticleWithSpace(type.getTypes().get(0).getGender(), flags));
builder.append("item frame " + type == null ? "" : "of " + type.toString(flags));
builder.append("rotated " + Classes.toString(rotation));
return builder.toString();
}

@Override
protected boolean equals_i(EntityData<?> entityData) {
if (!(entityData instanceof ItemFrameData other))
return false;
return type == null ? true : type.equals(other.type) && rotation == other.rotation;
}

@Override
protected int hashCode_i() {
int prime = 31;
int result = 1;
result = prime * result + (type == null ? 0 : type.hashCode());
result = prime * result + rotation.hashCode();
return result;
}

}
20 changes: 10 additions & 10 deletions src/main/java/ch/njol/skript/util/slot/ItemFrameSlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
* Represents contents of an item frame.
*/
public class ItemFrameSlot extends Slot {

private ItemFrame frame;

public ItemFrameSlot(ItemFrame frame) {
this.frame = frame;
}
Expand All @@ -28,25 +28,25 @@ public ItemStack getItem() {
public void setItem(@Nullable ItemStack item) {
frame.setItem(item);
}

@Override
public int getAmount() {
return 1;
}

@Override
public void setAmount(int amount) {}

@Override
public boolean isSameSlot(Slot o) {
if (o instanceof ItemFrameSlot) // Same item frame
return ((ItemFrameSlot) o).frame.equals(frame);
public boolean isSameSlot(Slot slot) {
if (slot instanceof ItemFrameSlot) // Same item frame
return ((ItemFrameSlot) slot).frame.equals(frame);
return false;
}

@Override
public String toString(@Nullable Event e, boolean debug) {
public String toString(@Nullable Event event, boolean debug) {
return Classes.toString(getItem());
}

}
15 changes: 14 additions & 1 deletion src/main/resources/lang/default.lang
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ entities:
pattern: lightning bolt(|1¦s)
item frame:
name: item frame¦s @an
pattern: item[ ]frame(|1¦s)
pattern: item[ ]frame(|1¦s) [(with|of) %-itemtype%] [[(with rotation|rotated)] %-rotation%]
magma cube:
name: magma cube¦s
pattern: magma (cube|slime)(|1¦s)
Expand Down Expand Up @@ -2548,6 +2548,17 @@ banner pattern types:
half_vertical_mirror: vertical half mirror banner pattern
half_horizontal_mirror: horizontal half mirror banner pattern

# -- Rotations --
rotations:
clockwise: clockwise, clockwise by 90 degrees, clockwise 90 degrees, 90 degrees
clockwise_135: clockwise 135, clockwise by 135 degrees, 135 degrees
clockwise_45: clockwise 45, clockwise by 45 degrees, 45 degrees
counter_clockwise: counter clockwise, counter clockwise by 90 degrees, counter clockwise 90 degrees, 270 degrees
counter_clockwise_45: counter clockwise 45, counter clockwise by 45 degrees, 315 degrees
flipped: flipped, flipped upside-down, flipped upside down, 180 degrees
flipped_45: flipped 45, flipped upside-down by 45 degrees, 225 degrees
none: none, nothing, no rotation, not rotated, 360 degrees

# -- Input Keys --
input keys:
forward: forward movement key, forward key
Expand Down Expand Up @@ -2659,6 +2670,8 @@ types:
bannerpatterntype: banner pattern type¦s @a
bannerpattern: banner pattern¦s @a
vehicle: vehicle¦s @a
itemframe: item frame¦s @an
rotation: rotation¦s @a

# Skript
weathertype: weather type¦s @a
Expand Down