Skip to content

Commit

Permalink
Feature/direction dependent block attachment (#681)
Browse files Browse the repository at this point in the history
* Attempt 1

* Attempt 5

* Solved! (incomeplete)

Needs a block whitelist

ty <3 ohnoey

* Add Lanterns + small refactor

* Remove commented code

* Refactor shorthanded variables

* Remove Debugging and useless variable

* Undo: Revert a conditional

* Made SupportUtils class

* Adding Reminders + More robust FaceAttachable checks

* Add directionDependentMaterials

* Fix Signs (only get wall signs as they are directional)

* Use `Tag.WALL_SIGNS` instead

* Created Tags.WALL_TORCHES and used that instead

---------

Co-authored-by: TylerS1066 <TylerS1066@users.noreply.github.com>
  • Loading branch information
Intybyte and TylerS1066 authored Aug 17, 2024
1 parent b23f98a commit 953f7d0
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 22 deletions.
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 @@ -174,4 +175,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 @@ -191,7 +188,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");
public static final NamespacedKey ALLOW_INTERNAL_COLLISION_EXPLOSION = buildKey("allow_internal_collision_explosion");
//endregion

Expand Down Expand Up @@ -395,6 +392,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

0 comments on commit 953f7d0

Please sign in to comment.