Skip to content

Commit

Permalink
Merge branch 'dev/feature' into feature/enchantment_prep
Browse files Browse the repository at this point in the history
  • Loading branch information
sovdeeth authored Jul 1, 2024
2 parents c28da37 + f1e0dd6 commit 0d5dc52
Show file tree
Hide file tree
Showing 30 changed files with 630 additions and 212 deletions.
11 changes: 10 additions & 1 deletion src/main/java/ch/njol/skript/aliases/Aliases.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import ch.njol.skript.config.Node;
import ch.njol.skript.config.SectionNode;
import ch.njol.skript.entity.EntityData;
import org.bukkit.entity.EntityType;
import org.skriptlang.skript.lang.script.Script;
import ch.njol.skript.lang.parser.ParserInstance;
import ch.njol.skript.localization.ArgsMessage;
Expand Down Expand Up @@ -431,7 +432,6 @@ private static void loadInternal() throws IOException {
Path aliasesPath = zipFs.getPath("/", "aliases-english");
assert aliasesPath != null;
loadDirectory(aliasesPath);
loadMissingAliases();
}
} catch (URISyntaxException e) {
assert false;
Expand All @@ -445,6 +445,9 @@ private static void loadInternal() throws IOException {
assert aliasesFolder != null;
loadDirectory(aliasesFolder);
}

// generate aliases from item names for any missing items
loadMissingAliases();

// Update tracked item types
for (Map.Entry<String, ItemType> entry : trackedTypes.entrySet()) {
Expand Down Expand Up @@ -554,10 +557,16 @@ public static EntityData<?> getRelatedEntity(ItemData data) {
* <p>Item types provided by this method are updated when aliases are
* reloaded. However, this also means they are tracked by aliases system
* and NOT necessarily garbage-collected.
*
* <p>Relying on this method to create item types is not safe,
* as users can change aliases at any point. ItemTypes should instead be created
* via {@link Material}s, {@link org.bukkit.Tag}s, or any other manual method.
*
* @param name Name of item to search from aliases.
* @return An item.
* @throws IllegalArgumentException When item is not found.
*/
@Deprecated(forRemoval = true, since = "2.9.0")
public static ItemType javaItemType(String name) {
ItemType type = parseItemType(name);
if (type == null) {
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/ch/njol/skript/aliases/ItemType.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Skull;
Expand Down Expand Up @@ -173,6 +174,18 @@ public ItemType(Material id) {
add_(new ItemData(id));
}

public ItemType(Material... ids) {
for (Material id : ids) {
add_(new ItemData(id));
}
}

public ItemType(Tag<Material> tag) {
for (Material id : tag.getValues()) {
add_(new ItemData(id));
}
}

public ItemType(Material id, String tags) {
add_(new ItemData(id, tags));
}
Expand Down
59 changes: 58 additions & 1 deletion src/main/java/ch/njol/skript/bukkitutil/ItemUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@
import ch.njol.skript.Skript;
import ch.njol.skript.aliases.ItemType;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.TreeType;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Fence;
import org.bukkit.block.data.type.Gate;
import org.bukkit.block.data.type.Wall;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
Expand Down Expand Up @@ -234,5 +240,56 @@ public static boolean isAir(Material type) {
public static Material getTreeSapling(TreeType treeType) {
return TREE_TO_SAPLING_MAP.get(treeType);
}



private static final boolean HAS_FENCE_TAGS = !Skript.isRunningMinecraft(1, 14);

/**
* Whether the block is a fence or a wall.
* @param block the block to check.
* @return whether the block is a fence/wall.
*/
public static boolean isFence(Block block) {
// TODO: 1.13 only, so remove in 2.10
if (!HAS_FENCE_TAGS) {
BlockData data = block.getBlockData();
return data instanceof Fence
|| data instanceof Wall
|| data instanceof Gate;
}

Material type = block.getType();
return Tag.FENCES.isTagged(type)
|| Tag.FENCE_GATES.isTagged(type)
|| Tag.WALLS.isTagged(type);
}

/**
* @param material The material to check
* @return whether the material is a full glass block
*/
public static boolean isGlass(Material material) {
switch (material) {
case GLASS:
case RED_STAINED_GLASS:
case ORANGE_STAINED_GLASS:
case YELLOW_STAINED_GLASS:
case LIGHT_BLUE_STAINED_GLASS:
case BLUE_STAINED_GLASS:
case CYAN_STAINED_GLASS:
case LIME_STAINED_GLASS:
case GREEN_STAINED_GLASS:
case MAGENTA_STAINED_GLASS:
case PURPLE_STAINED_GLASS:
case PINK_STAINED_GLASS:
case WHITE_STAINED_GLASS:
case LIGHT_GRAY_STAINED_GLASS:
case GRAY_STAINED_GLASS:
case BLACK_STAINED_GLASS:
case BROWN_STAINED_GLASS:
return true;
default:
return false;
}
}
}
90 changes: 50 additions & 40 deletions src/main/java/ch/njol/skript/bukkitutil/block/NewBlockCompat.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import ch.njol.skript.aliases.Aliases;
import ch.njol.skript.aliases.ItemType;
import ch.njol.skript.aliases.MatchQuality;
import ch.njol.skript.bukkitutil.ItemUtils;
import ch.njol.skript.variables.Variables;
import ch.njol.yggdrasil.Fields;
import org.bukkit.Bukkit;
Expand All @@ -31,10 +32,12 @@
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.BlockSupport;
import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.block.data.type.Bed;
import org.bukkit.block.data.type.Snow;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
Expand Down Expand Up @@ -141,15 +144,6 @@ public void deserialize(@NonNull Fields fields) throws StreamCorruptedException
}

private static class NewBlockSetter implements BlockSetter {

private ItemType floorTorch;
private ItemType wallTorch;

private ItemType specialTorchSides;
private ItemType specialTorchFloors;

private boolean typesLoaded = false;

private static final BlockFace[] CARDINAL_FACES =
new BlockFace[] {BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST};

Expand All @@ -158,14 +152,11 @@ public NewBlockSetter() {}

@Override
public void setBlock(Block block, Material type, @Nullable BlockValues values, int flags) {
if (!typesLoaded)
loadTypes();

boolean rotate = (flags | ROTATE) != 0;
boolean rotateForce = (flags | ROTATE_FORCE) != 0;
boolean rotateFixType = (flags | ROTATE_FIX_TYPE) != 0;
boolean multipart = (flags | MULTIPART) != 0;
boolean applyPhysics = (flags | APPLY_PHYSICS) != 0;
boolean rotate = (flags & ROTATE) != 0;
boolean rotateForce = (flags & ROTATE_FORCE) != 0;
boolean rotateFixType = (flags & ROTATE_FIX_TYPE) != 0;
boolean multipart = (flags & MULTIPART) != 0;
boolean applyPhysics = (flags & APPLY_PHYSICS) != 0;
NewBlockValues ourValues = null;
if (values != null)
ourValues = (NewBlockValues) values;
Expand All @@ -178,39 +169,31 @@ public void setBlock(Block block, Material type, @Nullable BlockValues values, i
*/
boolean placed = false;
if (rotate) {
if (floorTorch.isOfType(type) || (rotateFixType && wallTorch.isOfType(type))) {
if (type == Material.TORCH || (rotateFixType && type == Material.WALL_TORCH)) {
// If floor torch cannot be placed, try a wall torch
Block under = block.getRelative(0, -1, 0);
boolean canPlace = true;
if (!under.getType().isOccluding()) { // Usually cannot be placed, but there are exceptions
// TODO check for stairs and slabs, currently complicated since there is no 'any' alias
if (specialTorchFloors.isOfType(under)) {
canPlace = true;
} else {
canPlace = false;
}
}
boolean canPlace = canSupportFloorTorch(under);

// Can't really place a floor torch, try wall one instead
if (!canPlace) {
BlockFace face = findWallTorchSide(block);
if (face != null) { // Found better torch spot
block.setType(wallTorch.getMaterial());
block.setType(Material.WALL_TORCH);
Directional data = (Directional) block.getBlockData();
data.setFacing(face);
block.setBlockData(data, applyPhysics);
placed = true;
}
}
} else if (wallTorch.isOfType(type)) {
} else if (type == Material.WALL_TORCH) {
Directional data;
if (ourValues != null)
data = (Directional) ourValues.data;
else
data = (Directional) Bukkit.createBlockData(type);

Block relative = block.getRelative(data.getFacing());
if ((!relative.getType().isOccluding() && !specialTorchSides.isOfType(relative)) || rotateForce) {
if ((!canSupportWallTorch(relative, data.getFacing().getOppositeFace())) || rotateForce) {
// Attempt to figure out a better rotation
BlockFace face = findWallTorchSide(block);
if (face != null) { // Found better torch spot
Expand Down Expand Up @@ -294,22 +277,49 @@ public void setBlock(Block block, Material type, @Nullable BlockValues values, i
block.setBlockData(ourValues.data, applyPhysics);
}
}

private void loadTypes() {
floorTorch = Aliases.javaItemType("floor torch");
wallTorch = Aliases.javaItemType("wall torch");

specialTorchSides = Aliases.javaItemType("special torch sides");
specialTorchFloors = Aliases.javaItemType("special torch floors");

typesLoaded = true;

// 1.19+
// TODO: remove in 2.10
private static final boolean HAS_BLOCK_SUPPORT = Skript.classExists("org.bukkit.block.BlockSupport");

/**
* Returns whether this block can support a floor torch.
* @param block The block the torch will be placed on
* @return whether the block can support the torch.
*/
private static boolean canSupportFloorTorch(Block block) {
if (HAS_BLOCK_SUPPORT)
return block.getBlockData().isFaceSturdy(BlockFace.UP, BlockSupport.CENTER);

Material material = block.getType();
return (material.isOccluding()
|| canSupportWallTorch(block, null)
|| ItemUtils.isFence(block)
|| ItemUtils.isGlass(material)
|| material == Material.HOPPER
|| (material == Material.SNOW && (((Snow) block.getBlockData()).getLayers() == 8))
);
}

/**
* Returns whether this block can support a wall torch. In 1.19+, a face can be specified.
* @param block The block the torch will be placed on
* @param face The face the torch will be placed on (only considered in 1.19+)
* @return whether the block face can support the torch.
*/
private static boolean canSupportWallTorch(Block block, @Nullable BlockFace face) {
if (HAS_BLOCK_SUPPORT && face != null)
return block.getBlockData().isFaceSturdy(face, BlockSupport.FULL);

Material material = block.getType();
return material.isOccluding() || material == Material.SOUL_SAND || material == Material.SPAWNER;
}

@Nullable
private BlockFace findWallTorchSide(Block block) {
for (BlockFace face : CARDINAL_FACES) {
Block relative = block.getRelative(face);
if (relative.getType().isOccluding() || specialTorchSides.isOfType(relative))
if (relative.getType().isOccluding() || canSupportWallTorch(relative, face.getOppositeFace()))
return face.getOppositeFace(); // Torch can be rotated towards from this face
}

Expand Down
9 changes: 6 additions & 3 deletions src/main/java/ch/njol/skript/classes/data/BukkitClasses.java
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,8 @@ public String toVariableNameString(final ItemStack i) {
Classes.registerClass(biomeClassInfo
.user("biomes?")
.name("Biome")
.description("All possible biomes Minecraft uses to generate a world.")
.description("All possible biomes Minecraft uses to generate a world.",
"NOTE: Minecraft namespaces are supported, ex: 'minecraft:basalt_deltas'.")
.examples("biome at the player is desert")
.since("1.4.4")
.after("damagecause"));
Expand Down Expand Up @@ -1413,7 +1414,8 @@ public String toVariableNameString(FireworkEffect effect) {
Classes.registerClass(catTypeClassInfo
.user("cat ?(type|race)s?")
.name("Cat Type")
.description("Represents the race/type of a cat entity.")
.description("Represents the race/type of a cat entity.",
"NOTE: Minecraft namespaces are supported, ex: 'minecraft:british_shorthair'.")
.since("2.4")
.requiredPlugins("Minecraft 1.14 or newer")
.documentationId("CatType"));
Expand Down Expand Up @@ -1481,7 +1483,8 @@ public String toVariableNameString(EnchantmentOffer eo) {
.user("attribute ?types?")
.name("Attribute Type")
.description("Represents the type of an attribute. Note that this type does not contain any numerical values."
+ "See <a href='https://minecraft.wiki/w/Attribute#Attributes'>attribute types</a> for more info.")
+ "See <a href='https://minecraft.wiki/w/Attribute#Attributes'>attribute types</a> for more info.",
"NOTE: Minecraft namespaces are supported, ex: 'minecraft:generic.attack_damage'.")
.since("2.5"));

Classes.registerClass(new EnumClassInfo<>(Environment.class, "environment", "environments")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,12 +392,11 @@ public Block get(final BlockBreakEvent e) {
return new DelayedChangeBlock(e.getBlock());
}
}, 0);
ItemType stationaryWater = Aliases.javaItemType("stationary water");
EventValues.registerEventValue(BlockBreakEvent.class, Block.class, new Getter<Block, BlockBreakEvent>() {
@Override
public Block get(final BlockBreakEvent e) {
final BlockState s = e.getBlock().getState();
s.setType(s.getType() == Material.ICE ? stationaryWater.getMaterial() : Material.AIR);
s.setType(s.getType() == Material.ICE ? Material.WATER : Material.AIR);
s.setRawData((byte) 0);
return new BlockStateBlock(s, true);
}
Expand Down Expand Up @@ -760,12 +759,11 @@ public Block get(final PlayerBucketEmptyEvent e) {
return e.getBlockClicked().getRelative(e.getBlockFace());
}
}, -1);
ItemType stationaryLava = Aliases.javaItemType("stationary lava");
EventValues.registerEventValue(PlayerBucketEmptyEvent.class, Block.class, new Getter<Block, PlayerBucketEmptyEvent>() {
@Override
public Block get(final PlayerBucketEmptyEvent e) {
final BlockState s = e.getBlockClicked().getRelative(e.getBlockFace()).getState();
s.setType(e.getBucket() == Material.WATER_BUCKET ? stationaryWater.getMaterial() : stationaryLava.getMaterial());
s.setType(e.getBucket() == Material.WATER_BUCKET ? Material.WATER : Material.LAVA);
s.setRawData((byte) 0);
return new BlockStateBlock(s, true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -496,15 +496,14 @@ public boolean supportsOrdering() {
});

// DamageCause - ItemType
ItemType lava = Aliases.javaItemType("lava");
Comparators.registerComparator(DamageCause.class, ItemType.class, new Comparator<DamageCause, ItemType>() {
@Override
public Relation compare(DamageCause dc, ItemType t) {
switch (dc) {
case FIRE:
return Relation.get(t.isOfType(Material.FIRE));
case LAVA:
return Relation.get(t.equals(lava));
return Relation.get(t.getMaterial() == Material.LAVA);
case MAGIC:
return Relation.get(t.isOfType(Material.POTION));
case HOT_FLOOR:
Expand Down
Loading

0 comments on commit 0d5dc52

Please sign in to comment.