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

Feature/direction dependent block attachment #681

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand All @@ -48,9 +50,11 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -304,7 +308,6 @@ private void frontier() {
ConcurrentLinkedQueue<MovecraftLocation> nextFrontier = new ConcurrentLinkedQueue<>();
currentFrontier.add(startLocation);
currentFrontier.addAll(Arrays.stream(SHIFTS).map(startLocation::add).collect(Collectors.toList()));
visited.addAll(currentFrontier);
int threads = Runtime.getRuntime().availableProcessors();
while(!currentFrontier.isEmpty() && size.intValue() < type.getIntProperty(CraftType.MAX_SIZE) + threads) {
List<ForkJoinTask<?>> tasks = new ArrayList<>();
Expand All @@ -330,6 +333,14 @@ public String toString(){
private class DetectAction implements Runnable {
private final ConcurrentLinkedQueue<MovecraftLocation> currentFrontier;
private final ConcurrentLinkedQueue<MovecraftLocation> nextFrontier;
private static DetectionPredicate<MovecraftLocation> chain;

static {
chain = FORBIDDEN_BLOCK_VALIDATOR;
for(var validator : VALIDATORS) {
chain = chain.and(validator);
}
}

private DetectAction(ConcurrentLinkedQueue<MovecraftLocation> currentFrontier, ConcurrentLinkedQueue<MovecraftLocation> nextFrontier) {
this.currentFrontier = currentFrontier;
Expand All @@ -339,31 +350,42 @@ private DetectAction(ConcurrentLinkedQueue<MovecraftLocation> currentFrontier, C
@Override
public void run() {
MovecraftLocation probe;
EnumSet<Material> directionalDependent = type.getMaterialSetProperty(CraftType.DIRECTIONAL_DEPENDENT_MATERIALS);

while((probe = currentFrontier.poll()) != null) {
visitedMaterials.computeIfAbsent(movecraftWorld.getMaterial(probe), Functions.forSupplier(ConcurrentLinkedDeque::new)).add(probe);
BlockData blockData = movecraftWorld.getData(probe);
Material material = blockData.getMaterial();

Optional<BlockFace> blockDataOptional = SupportUtils.getSupportFace(blockData, directionalDependent);
if (blockDataOptional.isPresent()) {
BlockFace facing = blockDataOptional.get();
MovecraftLocation relativeLoc = probe.getRelative(facing);

if (!legal.contains(relativeLoc))
continue;
}

if(!visited.add(probe))
continue;

visitedMaterials.computeIfAbsent(material, Functions.forSupplier(ConcurrentLinkedDeque::new)).add(probe);
if(!ALLOWED_BLOCK_VALIDATOR.validate(probe, type, movecraftWorld, player).isSucess())
continue;

DetectionPredicate<MovecraftLocation> chain = FORBIDDEN_BLOCK_VALIDATOR;
for(var validator : VALIDATORS) {
chain = chain.and(validator);
}
var result = chain.validate(probe, type, movecraftWorld, player);

if(result.isSucess()) {
if (result.isSucess()) {
legal.add(probe);
if(Tags.FLUID.contains(movecraftWorld.getMaterial(probe)))
if (Tags.FLUID.contains(material))
fluid.add(probe);

size.increment();
materials.computeIfAbsent(movecraftWorld.getMaterial(probe), Functions.forSupplier(ConcurrentLinkedDeque::new)).add(probe);
for(MovecraftLocation shift : SHIFTS) {
materials.computeIfAbsent(material, Functions.forSupplier(ConcurrentLinkedDeque::new)).add(probe);
for (MovecraftLocation shift : SHIFTS) {
var shifted = probe.add(shift);
if(visited.add(shifted))
nextFrontier.add(shifted);
nextFrontier.add(shifted);
}
}
else {
} else {
illegal.add(probe);
audience.sendMessage(Component.text(result.getMessage()));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package net.countercraft.movecraft.processing.tasks.detection;

import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
import org.bukkit.block.data.FaceAttachable;
import org.bukkit.block.data.type.Lantern;

import java.util.EnumSet;
import java.util.Optional;

/**
* @author Intybyte/Vaan1310
* An util craft that uses block data to get its supporting block
*/

public class SupportUtils {
public static Optional<BlockFace> getSupportFace(BlockData data, EnumSet<Material> directionalDependent) {

Material material = data.getMaterial();
if (!directionalDependent.contains(material)) {
return Optional.empty();
}

//TODO: Use pattern matched switch statements once we update do Java 21
//TODO: This should become Hangable instead when we drop support for 1.18
if (data instanceof Lantern lantern)
return Optional.of(lantern.isHanging() ? BlockFace.UP : BlockFace.DOWN);

if (data instanceof Directional directional) {
BlockFace normalCase = directional.getFacing().getOppositeFace();

if (data instanceof FaceAttachable faceAttachable) {
return switch (faceAttachable.getAttachedFace()) {
case FLOOR -> Optional.of(BlockFace.DOWN);
case WALL -> Optional.of(normalCase);
case CEILING -> Optional.of(BlockFace.UP);
};
}

return Optional.of(normalCase);
}

return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.google.common.primitives.UnsignedInteger;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.jetbrains.annotations.NotNull;

import static net.countercraft.movecraft.util.BitMath.mask;
Expand Down Expand Up @@ -154,4 +155,8 @@ public int compareTo(@NotNull MovecraftLocation other) {
}
return 0;
}

public MovecraftLocation getRelative(BlockFace facing) {
return this.translate(facing.getModX(), facing.getModY(), facing.getModZ());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@
import net.countercraft.movecraft.util.Tags;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.sound.Sound;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
import org.bukkit.*;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -189,6 +186,7 @@ final public class CraftType {
public static final NamespacedKey CRUISE_ON_PILOT_LIFETIME = buildKey("cruise_on_pilot_lifetime");

public static final NamespacedKey EXPLOSION_ARMING_TIME = buildKey("explosion_arming_time");
public static final NamespacedKey DIRECTIONAL_DEPENDENT_MATERIALS = buildKey("directional_dependent_materials");
//endregion

@Contract("_ -> new")
Expand Down Expand Up @@ -391,6 +389,13 @@ public static void registerTypeValidator(Predicate<CraftType> validator, String
/* Optional properties */
registerProperty(new RequiredBlockProperty("flyblocks", FLY_BLOCKS, type -> new HashSet<>()));
registerProperty(new RequiredBlockProperty("detectionblocks", DETECTION_BLOCKS, type -> new HashSet<>()));
registerProperty(new MaterialSetProperty("directionDependentMaterials", DIRECTIONAL_DEPENDENT_MATERIALS, type -> {
var set = EnumSet.of(Material.LADDER, Material.LEVER, Material.GRINDSTONE, Material.LANTERN);
set.addAll(Tag.WALL_SIGNS.getValues());
set.addAll(Tags.WALL_TORCHES);
return set;
}));

registerProperty(new ObjectPropertyImpl("forbiddenSignStrings", FORBIDDEN_SIGN_STRINGS,
(data, type, fileKey, namespacedKey) -> data.getStringListOrEmpty(fileKey).stream().map(
String::toLowerCase).collect(Collectors.toSet()),
Expand Down
4 changes: 1 addition & 3 deletions api/src/main/java/net/countercraft/movecraft/util/Tags.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@
import org.bukkit.Keyed;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.Tag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;

public class Tags {
public static final EnumSet<Material> WATER = EnumSet.of(Material.WATER, Material.BUBBLE_COLUMN);
Expand All @@ -22,6 +19,7 @@ public class Tags {
public static final EnumSet<Material> FRAGILE_MATERIALS = EnumSet.noneOf(Material.class);
public static final EnumSet<Material> FALL_THROUGH_BLOCKS = EnumSet.noneOf(Material.class);
public static final EnumSet<Material> BUCKETS = EnumSet.of(Material.LAVA_BUCKET, Material.WATER_BUCKET, Material.MILK_BUCKET, Material.COD_BUCKET, Material.PUFFERFISH_BUCKET, Material.SALMON_BUCKET, Material.TROPICAL_FISH_BUCKET);
public static final EnumSet<Material> WALL_TORCHES = EnumSet.of(Material.WALL_TORCH, Material.SOUL_WALL_TORCH, Material.REDSTONE_WALL_TORCH);

static {
FRAGILE_MATERIALS.add(Material.PISTON_HEAD);
Expand Down