Skip to content

Commit

Permalink
move respect invisibility config to per-block option
Browse files Browse the repository at this point in the history
  • Loading branch information
bl4ckscor3 committed May 24, 2024
1 parent 0092259 commit 6ddf36c
Show file tree
Hide file tree
Showing 24 changed files with 124 additions and 52 deletions.
3 changes: 3 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
- Change: The "preventReinforcedFloorGlitching" configuration option no longer affects players trying to glitch through reinforced blocks that they are the owner of
- Change: Players in creative mode can once again use the codebreaker on their own blocks
- Change: When picking up a placed sentry, the resulting sentry item will now be named according to the custom name of the removed sentry
- Change: The "respect_invisibility" config setting has been moved to a per-block option
- Change: The Sentry can no longer attack invisible entities
- API: Changed constructors for IntOption and DoubleOption, they are now always sliders by default
- API: Removed FloatOption. Use DoubleOption instead
- API: IModuleInventory is no longer hardcoded to just block entities
Expand All @@ -19,6 +21,7 @@
- API: New Option "EntityDataWrappedOption" that connects an EntityDataAccessor with an Option, and corresponding converter method "wrapForEntityData"
- API: New method Option#getValueText for getting a textual representation of the option's value
- API: ICustomizable#onOptionChanged now has a proper generic type
- API: New method IViewActivated#isConsideredInvisible
- Fix: Trying to place a Panic Button on top of powdered snow crashes the game
- Fix: Occasional crash when opening the inventory in creative mode in certain situations
- Fix: Reinforced fence gates don't properly retain their owner when reloading the world
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ public static class Server {
public IntValue inventoryScannerRange;
public IntValue maxAlarmRange;
public BooleanValue allowBlockClaim;
public BooleanValue respectInvisibility;
public BooleanValue reinforcedBlockTint;
public BooleanValue forceReinforcedBlockTint;
public BooleanValue retinalScannerFace;
Expand Down Expand Up @@ -142,10 +141,6 @@ public static class Server {
.comment("Allow claiming unowned blocks?")
.define("allowBlockClaim", false);

respectInvisibility = builder
.comment("Should the sentry/inventory scanner/laser block/etc. ignore players and entities that are invisible?")
.define("respect_invisibility", false);

reinforcedBlockTint = builder
.comment("Should reinforced blocks' textures be slightly darker than their vanilla counterparts? This does nothing unless force_reinforced_block_tint is set to true.")
.define("reinforced_block_tint", true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.List;

import net.geforcemods.securitycraft.util.Utils;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
Expand Down Expand Up @@ -31,7 +30,7 @@ default void checkView(Level level, BlockPos pos) {
}

double maximumDistance = getMaximumDistance();
List<LivingEntity> entities = level.getEntitiesOfClass(LivingEntity.class, new AABB(pos).inflate(maximumDistance), e -> e.canBeSeenByAnyone() && !Utils.isEntityInvisible(e) && (!activatedOnlyByPlayer() || e instanceof Player));
List<LivingEntity> entities = level.getEntitiesOfClass(LivingEntity.class, new AABB(pos).inflate(maximumDistance), e -> e.canBeSeenByAnyone() && !isConsideredInvisible(e) && (!activatedOnlyByPlayer() || e instanceof Player));

for (LivingEntity entity : entities) {
double eyeHeight = entity.getEyeHeight();
Expand Down Expand Up @@ -85,4 +84,13 @@ public default boolean activatedOnlyByPlayer() {
* @return The maximum distance in blocks from which a view check is performed
*/
public double getMaximumDistance();

/**
* Returns whether the given entity is treated as being invisible. This does not necessarily need to match whether the entity
* has the invisibility effect
*
* @param entity The living entity to check
* @return true if the entity is considered invisible, false otherwise
*/
public boolean isConsideredInvisible(LivingEntity entity);
}
21 changes: 21 additions & 0 deletions src/main/java/net/geforcemods/securitycraft/api/Option.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import net.minecraft.network.chat.Component;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.LivingEntity;

/**
* A class that allows blocks that have {@link ICustomizable} block entities to have custom, per-block options that are
Expand Down Expand Up @@ -214,6 +216,25 @@ public String getKey(String denotation) {
}
}

public static class RespectInvisibilityOption extends BooleanOption {
public RespectInvisibilityOption() {
this(false);
}

public RespectInvisibilityOption(Boolean value) {
super("respectInvisibility", value);
}

@Override
public String getKey(String denotation) {
return "option.generic.respectInvisibility";
}

public boolean isConsideredInvisible(LivingEntity entity) {
return get() && entity.hasEffect(MobEffects.INVISIBILITY);
}
}

public static class SendAllowlistMessageOption extends BooleanOption {
public SendAllowlistMessageOption(Boolean value) {
super("sendAllowlistMessage", value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.geforcemods.securitycraft.api.Option;
import net.geforcemods.securitycraft.api.Option.IgnoreOwnerOption;
import net.geforcemods.securitycraft.api.Option.IntOption;
import net.geforcemods.securitycraft.api.Option.RespectInvisibilityOption;
import net.geforcemods.securitycraft.api.Option.TargetingModeOption;
import net.geforcemods.securitycraft.blocks.mines.ClaymoreBlock;
import net.geforcemods.securitycraft.inventory.InsertOnlyInvWrapper;
Expand Down Expand Up @@ -39,6 +40,7 @@ public class ClaymoreBlockEntity extends CustomizableBlockEntity implements ITic
private IntOption range = new IntOption("range", 5, 1, 10, 1);
private IgnoreOwnerOption ignoreOwner = new IgnoreOwnerOption(true);
private TargetingModeOption targetingMode = new TargetingModeOption(TargetingMode.PLAYERS_AND_MOBS);
private RespectInvisibilityOption respectInvisibility = new RespectInvisibilityOption();
private LensContainer lens = new LensContainer(1);
private int cooldown = -1;

Expand Down Expand Up @@ -72,7 +74,7 @@ public void tick(Level level, BlockPos pos, BlockState state) { //server only as
default -> new AABB(pos);
};

level.getEntitiesOfClass(LivingEntity.class, area, e -> mode.canAttackEntity(e, this, true)).stream().findFirst().ifPresent(e -> {
level.getEntitiesOfClass(LivingEntity.class, area, e -> mode.canAttackEntity(e, this, respectInvisibility::isConsideredInvisible)).stream().findFirst().ifPresent(e -> {
cooldown = 20;
level.playSound(null, BlockPos.containing(worldPosition.getX() + 0.5D, worldPosition.getY() + 0.5D, worldPosition.getZ() + 0.5D), SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.3F, 0.6F);
});
Expand Down Expand Up @@ -122,7 +124,7 @@ public Container getLensContainer() {
@Override
public Option<?>[] customOptions() {
return new Option[] {
range, ignoreOwner, targetingMode
range, ignoreOwner, targetingMode, respectInvisibility
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.geforcemods.securitycraft.api.Option.DisabledOption;
import net.geforcemods.securitycraft.api.Option.IgnoreOwnerOption;
import net.geforcemods.securitycraft.api.Option.IntOption;
import net.geforcemods.securitycraft.api.Option.RespectInvisibilityOption;
import net.geforcemods.securitycraft.api.Option.TargetingModeOption;
import net.geforcemods.securitycraft.blocks.mines.IMSBlock;
import net.geforcemods.securitycraft.entity.IMSBomb;
Expand All @@ -32,6 +33,7 @@ public class IMSBlockEntity extends CustomizableBlockEntity implements ITickingB
private DisabledOption disabled = new DisabledOption(false);
private IgnoreOwnerOption ignoreOwner = new IgnoreOwnerOption(true);
private TargetingModeOption targetingMode = new TargetingModeOption(TargetingMode.PLAYERS_AND_MOBS);
private RespectInvisibilityOption respectInvisibility = new RespectInvisibilityOption();
private int bombsRemaining = 4;
private boolean updateBombCount = false;
private int attackTime = getAttackInterval();
Expand Down Expand Up @@ -83,7 +85,7 @@ private void launchMine(Level level, BlockPos pos) {
AABB area = new AABB(pos).inflate(range.get());
TargetingMode mode = getTargetingMode();

level.getEntitiesOfClass(LivingEntity.class, area, e -> (e instanceof Player || e instanceof Monster) && mode.canAttackEntity(e, this, true)).stream().findFirst().ifPresent(e -> {
level.getEntitiesOfClass(LivingEntity.class, area, e -> (e instanceof Player || e instanceof Monster) && mode.canAttackEntity(e, this, respectInvisibility::isConsideredInvisible)).stream().findFirst().ifPresent(e -> {
double addToX = bombsRemaining == 4 || bombsRemaining == 3 ? 0.84375D : 0.0D; //0.84375 is the offset towards the bomb's position in the model
double addToZ = bombsRemaining == 4 || bombsRemaining == 2 ? 0.84375D : 0.0D;
int launchHeight = getLaunchHeight();
Expand Down Expand Up @@ -157,7 +159,7 @@ public ModuleType[] acceptedModules() {
@Override
public Option<?>[] customOptions() {
return new Option[] {
range, disabled, ignoreOwner, targetingMode
range, disabled, ignoreOwner, targetingMode, respectInvisibility
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import net.geforcemods.securitycraft.api.Option.DisabledOption;
import net.geforcemods.securitycraft.api.Option.IgnoreOwnerOption;
import net.geforcemods.securitycraft.api.Option.IntOption;
import net.geforcemods.securitycraft.api.Option.RespectInvisibilityOption;
import net.geforcemods.securitycraft.api.Option.SignalLengthOption;
import net.geforcemods.securitycraft.blocks.InventoryScannerBlock;
import net.geforcemods.securitycraft.blocks.InventoryScannerFieldBlock;
Expand All @@ -34,6 +35,7 @@
import net.minecraft.world.ContainerListener;
import net.minecraft.world.Containers;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
Expand All @@ -51,6 +53,7 @@ public class InventoryScannerBlockEntity extends DisguisableBlockEntity implemen
private DisabledOption disabled = new DisabledOption(false);
private IgnoreOwnerOption ignoreOwner = new IgnoreOwnerOption(true);
private IntOption signalLength = new SignalLengthOption(60);
private RespectInvisibilityOption respectInvisibility = new RespectInvisibilityOption();
private NonNullList<ItemStack> inventoryContents = NonNullList.<ItemStack>withSize(37, ItemStack.EMPTY);
private boolean providePower;
private int signalCooldown, togglePowerCooldown;
Expand Down Expand Up @@ -523,10 +526,14 @@ public void setSignalLength(int signalLength) {
setChanged();
}

public boolean isConsideredInvisible(LivingEntity entity) {
return respectInvisibility.isConsideredInvisible(entity);
}

@Override
public Option<?>[] customOptions() {
return new Option[] {
horizontal, solidifyField, disabled, ignoreOwner, signalLength
horizontal, solidifyField, disabled, ignoreOwner, signalLength, respectInvisibility
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import net.geforcemods.securitycraft.api.Option.DisabledOption;
import net.geforcemods.securitycraft.api.Option.IgnoreOwnerOption;
import net.geforcemods.securitycraft.api.Option.IntOption;
import net.geforcemods.securitycraft.api.Option.RespectInvisibilityOption;
import net.geforcemods.securitycraft.api.Option.SignalLengthOption;
import net.geforcemods.securitycraft.api.Owner;
import net.geforcemods.securitycraft.blocks.LaserBlock;
Expand All @@ -36,6 +37,7 @@
import net.minecraft.world.Container;
import net.minecraft.world.ContainerListener;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
Expand All @@ -56,6 +58,7 @@ public void toggle() {
};
private IgnoreOwnerOption ignoreOwner = new IgnoreOwnerOption(true);
private IntOption signalLength = new SignalLengthOption(50);
private RespectInvisibilityOption respectInvisibility = new RespectInvisibilityOption();
private Map<Direction, Boolean> sideConfig = Util.make(() -> {
EnumMap<Direction, Boolean> map = new EnumMap<>(Direction.class);

Expand Down Expand Up @@ -120,16 +123,20 @@ protected void onLinkedBlockAction(ILinkedAction action, List<LinkableBlockEntit
if (action instanceof ILinkedAction.OptionChanged<?> optionChanged) {
Option<?> option = optionChanged.option();

if (option.getName().equals("disabled")) {
if (option.getName().equals(disabled.getName())) {
disabled.copy(option);
setLasersAccordingToDisabledOption();
}
else if (option.getName().equals("ignoreOwner"))
else if (option.getName().equals(ignoreOwner.getName()))
ignoreOwner.copy(option);
else if (option.getName().equals("signalLength")) {
else if (option.getName().equals(signalLength.getName())) {
signalLength.copy(option);
turnOffRedstoneOutput();
}
else if (option.getName().equals(respectInvisibility.getName()))
respectInvisibility.copy(option);
else
throw new UnsupportedOperationException("Unhandled option synchronization in laser block! " + option.getName());
}
else if (action instanceof ILinkedAction.ModuleInserted moduleInserted)
insertModule(moduleInserted.stack(), moduleInserted.wasModuleToggled());
Expand Down Expand Up @@ -276,7 +283,7 @@ public ModuleType[] acceptedModules() {
@Override
public Option<?>[] customOptions() {
return new Option[] {
disabled, ignoreOwner, signalLength
disabled, ignoreOwner, signalLength, respectInvisibility
};
}

Expand All @@ -298,6 +305,10 @@ public int getSignalLength() {
return signalLength.get();
}

public boolean isConsideredInvisible(LivingEntity entity) {
return respectInvisibility.isConsideredInvisible(entity);
}

public void setLastToggleTime(long lastToggleTime) {
this.lastToggleTime = lastToggleTime;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
import net.geforcemods.securitycraft.api.Option.BooleanOption;
import net.geforcemods.securitycraft.api.Option.DisabledOption;
import net.geforcemods.securitycraft.api.Option.DoubleOption;
import net.geforcemods.securitycraft.api.Option.RespectInvisibilityOption;
import net.geforcemods.securitycraft.blocks.MotionActivatedLightBlock;
import net.geforcemods.securitycraft.entity.sentry.Sentry;
import net.geforcemods.securitycraft.misc.ModuleType;
import net.geforcemods.securitycraft.util.ITickingBlockEntity;
import net.geforcemods.securitycraft.util.Utils;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.decoration.ArmorStand;
Expand All @@ -24,6 +24,7 @@ public class MotionActivatedLightBlockEntity extends CustomizableBlockEntity imp
private static final int TICKS_BETWEEN_ATTACKS = 5;
private DoubleOption searchRadiusOption = new DoubleOption("searchRadius", 5.0D, 5.0D, 20.0D, 1.0D);
private DisabledOption disabled = new DisabledOption(false);
private RespectInvisibilityOption respectInvisibility = new RespectInvisibilityOption();
private int cooldown = TICKS_BETWEEN_ATTACKS;

public MotionActivatedLightBlockEntity(BlockPos pos, BlockState state) {
Expand All @@ -35,7 +36,7 @@ public void tick(Level level, BlockPos pos, BlockState state) {
if (isDisabled() || cooldown-- > 0)
return;

List<LivingEntity> entities = level.getEntitiesOfClass(LivingEntity.class, new AABB(pos).inflate(searchRadiusOption.get()), e -> !Utils.isEntityInvisible(e) && e.canBeSeenByAnyone() && !(e instanceof Sentry || e instanceof ArmorStand));
List<LivingEntity> entities = level.getEntitiesOfClass(LivingEntity.class, new AABB(pos).inflate(searchRadiusOption.get()), e -> !respectInvisibility.isConsideredInvisible(e) && e.canBeSeenByAnyone() && !(e instanceof Sentry || e instanceof ArmorStand));
boolean shouldBeOn = !entities.isEmpty();

if (state.getValue(MotionActivatedLightBlock.LIT) != shouldBeOn)
Expand All @@ -61,7 +62,7 @@ public ModuleType[] acceptedModules() {
@Override
public Option<?>[] customOptions() {
return new Option<?>[] {
searchRadiusOption, disabled
searchRadiusOption, disabled, respectInvisibility
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import net.geforcemods.securitycraft.api.Option.DoubleOption;
import net.geforcemods.securitycraft.api.Option.IgnoreOwnerOption;
import net.geforcemods.securitycraft.api.Option.IntOption;
import net.geforcemods.securitycraft.api.Option.RespectInvisibilityOption;
import net.geforcemods.securitycraft.api.Owner;
import net.geforcemods.securitycraft.blocks.PortableRadarBlock;
import net.geforcemods.securitycraft.misc.ModuleType;
Expand All @@ -37,6 +38,7 @@ public class PortableRadarBlockEntity extends CustomizableBlockEntity implements
private BooleanOption repeatMessageOption = new BooleanOption("repeatMessage", true);
private DisabledOption disabled = new DisabledOption(false);
private IgnoreOwnerOption ignoreOwner = new IgnoreOwnerOption(true);
private RespectInvisibilityOption respectInvisibility = new RespectInvisibilityOption();
private boolean shouldSendNewMessage = true;
private Owner lastPlayer = new Owner();
private int ticksUntilNextSearch = getSearchDelay();
Expand All @@ -51,7 +53,7 @@ public void tick(Level level, BlockPos pos, BlockState state) {
ticksUntilNextSearch = getSearchDelay();

AABB area = new AABB(pos).inflate(getSearchRadius());
List<Player> closebyPlayers = level.getEntitiesOfClass(Player.class, area, e -> !(isOwnedBy(e) && ignoresOwner()) && !isAllowed(e) && e.canBeSeenByAnyone() && !Utils.isEntityInvisible(e));
List<Player> closebyPlayers = level.getEntitiesOfClass(Player.class, area, e -> !(isOwnedBy(e) && ignoresOwner()) && !isAllowed(e) && e.canBeSeenByAnyone() && !respectInvisibility.isConsideredInvisible(e));

if (isModuleEnabled(ModuleType.REDSTONE))
PortableRadarBlock.togglePowerOutput(level, pos, !closebyPlayers.isEmpty());
Expand Down Expand Up @@ -163,7 +165,7 @@ public ModuleType[] acceptedModules() {
@Override
public Option<?>[] customOptions() {
return new Option[] {
searchRadiusOption, searchDelayOption, repeatMessageOption, disabled, ignoreOwner
searchRadiusOption, searchDelayOption, repeatMessageOption, disabled, ignoreOwner, respectInvisibility
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import net.geforcemods.securitycraft.api.Option;
import net.geforcemods.securitycraft.api.Option.DisabledOption;
import net.geforcemods.securitycraft.api.Option.IgnoreOwnerOption;
import net.geforcemods.securitycraft.api.Option.RespectInvisibilityOption;
import net.geforcemods.securitycraft.blocks.ProtectoBlock;
import net.geforcemods.securitycraft.entity.sentry.Sentry;
import net.geforcemods.securitycraft.misc.ModuleType;
import net.geforcemods.securitycraft.util.ITickingBlockEntity;
import net.geforcemods.securitycraft.util.LevelUtils;
import net.geforcemods.securitycraft.util.Utils;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.OwnableEntity;
Expand All @@ -29,6 +29,7 @@ public class ProtectoBlockEntity extends DisguisableBlockEntity implements ITick
private int ticksBetweenAttacks = isModuleEnabled(ModuleType.SPEED) ? FAST_SPEED : SLOW_SPEED;
private DisabledOption disabled = new DisabledOption(false);
private IgnoreOwnerOption ignoreOwner = new IgnoreOwnerOption(true);
private RespectInvisibilityOption respectInvisibility = new RespectInvisibilityOption();

public ProtectoBlockEntity(BlockPos pos, BlockState state) {
super(SCContent.PROTECTO_BLOCK_ENTITY.get(), pos, state);
Expand All @@ -49,7 +50,7 @@ public void tick(Level level, BlockPos pos, BlockState state) {
boolean shouldDeactivate = false;

for (LivingEntity entity : entities) {
if (!(entity instanceof Sentry) && !Utils.isEntityInvisible(entity)) {
if (!(entity instanceof Sentry) && !respectInvisibility.isConsideredInvisible(entity)) {
if (entity instanceof Player player && (player.isCreative() || !player.canBeSeenByAnyone() || (isOwnedBy(player) && ignoresOwner()) || isAllowed(entity)) || entity instanceof OwnableEntity ownableEntity && allowsOwnableEntity(ownableEntity))
continue;

Expand Down Expand Up @@ -96,7 +97,7 @@ public ModuleType[] acceptedModules() {
@Override
public Option<?>[] customOptions() {
return new Option[] {
disabled, ignoreOwner
disabled, ignoreOwner, respectInvisibility
};
}

Expand Down
Loading

0 comments on commit 6ddf36c

Please sign in to comment.