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

Added Optional Offline Protect Only Mode and more #330

Open
wants to merge 5 commits into
base: 1.19/dev
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
31 changes: 25 additions & 6 deletions common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunks.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MobSpawnType;
Expand Down Expand Up @@ -118,10 +119,11 @@ public FTBChunks() {
PlayerEvent.FILL_BUCKET.register(this::fillBucket);
PlayerEvent.PLAYER_CLONE.register(this::playerCloned);
PlayerEvent.CHANGE_DIMENSION.register(this::playerChangedDimension);
PlayerEvent.ATTACK_ENTITY.register(this::playerAttackEntity);
PlayerEvent.ATTACK_ENTITY.register(this::playerAttackNonLivingEntity);

EntityEvent.ENTER_SECTION.register(this::enterSection);
EntityEvent.LIVING_CHECK_SPAWN.register(this::checkSpawn);
EntityEvent.LIVING_HURT.register(this::livingEntityHurt);

ExplosionEvent.DETONATE.register(this::explosionDetonate);

Expand All @@ -137,7 +139,7 @@ public FTBChunks() {
}
}

private EventResult playerAttackEntity(Player player, Level level, Entity entity, InteractionHand interactionHand, @Nullable EntityHitResult entityHitResult) {
private EventResult playerAttackNonLivingEntity(Player player, Level level, Entity entity, InteractionHand interactionHand, @Nullable EntityHitResult entityHitResult) {
// note: intentionally does not prevent attacking living entities;
// this is for preventing griefing of entities like paintings & item frames
if (player instanceof ServerPlayer && !(entity instanceof LivingEntity) && FTBChunksAPI.getManager().protect(player, interactionHand, entity.blockPosition(), Protection.ATTACK_NONLIVING_ENTITY, entity)) {
Expand All @@ -147,6 +149,22 @@ private EventResult playerAttackEntity(Player player, Level level, Entity entity
return EventResult.pass();
}

private EventResult livingEntityHurt(LivingEntity livingEntity, DamageSource damageSource, float damage) {
if (livingEntity.level.isClientSide || !FTBChunksAPI.isManagerLoaded()) return EventResult.pass();
if (damageSource.getEntity() instanceof ServerPlayer player) {
if (FTBChunksAPI.getManager().protect(player, player.swingingArm, livingEntity.blockPosition(), Protection.ATTACK_LIVING_ENTITY, livingEntity)) {
return EventResult.interruptFalse();
}
} else if (livingEntity.getType().is(FTBChunksAPI.LIVING_ENTITY_ATTACK_BLACKLIST_TAG)) { // this block protects the entities from unknown sources
ClaimedChunk chunk = FTBChunksAPI.getManager().getChunk(new ChunkDimPos(livingEntity.level, livingEntity.blockPosition()));
if (chunk != null) {
return EventResult.interruptFalse();
}
}

return EventResult.pass();
}

private void playerTickPost(Player player) {
if (player.level.isClientSide && player.level.getGameTime() % 20 == 0) {
FTBChunks.PROXY.maybeClearDeathpoint(player);
Expand Down Expand Up @@ -234,6 +252,8 @@ public void loggedOut(ServerPlayer player) {
// last player on the team to log out; unforce chunks if the team can't do offline chunk-loading
data.updateChunkTickets(false);
}

data.setLastLogoffTime(System.currentTimeMillis());
}

private void teamCreated(TeamCreatedEvent teamEvent) {
Expand All @@ -251,10 +271,9 @@ private void teamSaved(TeamEvent teamEvent) {
public EventResult blockLeftClick(Player player, InteractionHand hand, BlockPos pos, Direction face) {
// calling architectury stub method
//noinspection ConstantConditions
if (player instanceof ServerPlayer && FTBChunksAPI.getManager().protect(player, hand, pos, FTBChunksExpected.getBlockBreakProtection(), null)) {
if (player instanceof ServerPlayer && FTBChunksAPI.getManager().protect(player, hand, pos, FTBChunksExpected.getBlockLeftClickProtection(), null)) {
return EventResult.interruptFalse();
}

return EventResult.pass();
}

Expand Down Expand Up @@ -288,10 +307,9 @@ private EventResult interactEntity(Player player, Entity entity, InteractionHand
}

public EventResult blockBreak(Level level, BlockPos pos, BlockState blockState, ServerPlayer player, @Nullable IntValue intValue) {
if (FTBChunksAPI.getManager().protect(player, InteractionHand.MAIN_HAND, pos, FTBChunksExpected.getBlockBreakProtection(), null)) {
if (FTBChunksAPI.getManager().protect(player, InteractionHand.MAIN_HAND, pos, FTBChunksExpected.getBlockBreakProtection(), null, true)) {
return EventResult.interruptFalse();
}

return EventResult.pass();
}

Expand Down Expand Up @@ -436,6 +454,7 @@ private void teamConfig(TeamCollectPropertiesEvent event) {
event.add(FTBChunksTeamData.ALLOW_ALL_FAKE_PLAYERS);
event.add(FTBChunksTeamData.ALLOW_NAMED_FAKE_PLAYERS);
event.add(FTBChunksTeamData.ALLOW_FAKE_PLAYERS_BY_ID);
event.add(FTBChunksTeamData.ALLOW_ATTACK_BLACKLISTED_ENTITIES);

// block edit/interact properties vary on forge & fabric
FTBChunksExpected.getPlatformSpecificProperties(event);
Expand Down
19 changes: 19 additions & 0 deletions common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunksCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import net.minecraft.util.Mth;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Comparator;
Expand Down Expand Up @@ -173,6 +174,14 @@ public static void registerCommands(CommandDispatcher<CommandSourceStack> dispat
.executes(context -> viewLoadedChunks(context.getSource(), DimensionArgument.getDimension(context, "dimension")))
)
)
.then(Commands.literal("reset_block_break_counter")
.then(Commands.literal("all")
.executes(context -> resetBlockBreakCounter(context.getSource(), null))
)
.then(Commands.argument("team", TeamArgument.create())
.executes(context -> resetBlockBreakCounter(context.getSource(), TeamArgument.get(context, "team")))
)
)
)
.then(Commands.literal("block_color")
.requires(source -> source.getServer().isSingleplayer())
Expand Down Expand Up @@ -505,4 +514,14 @@ private static ColumnPos toColumn(Vec3 pos) {
private static Team selfTeam(CommandSourceStack source) throws CommandSyntaxException {
return FTBTeamsAPI.getPlayerTeam(source.getPlayerOrException());
}

private static int resetBlockBreakCounter(CommandSourceStack source, @Nullable Team team) {
if (team == null) {
FTBChunksAPI.getManager().getAllTeamData().forEach(FTBChunksTeamData::resetBrokenBlocksCounter);
} else {
FTBChunksTeamData data = FTBChunksAPI.getManager().getData(team);
data.resetBrokenBlocksCounter();
}
return 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@ public static Protection getBlockInteractProtection() {
public static Protection getBlockBreakProtection() {
throw new AssertionError();
}

@ExpectPlatform
public static Protection getBlockLeftClickProtection() {
throw new AssertionError();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ public interface FTBChunksWorldConfig {
EnumValue<PartyLimitMode> PARTY_LIMIT_MODE = CONFIG.getEnum("party_limit_mode", PartyLimitMode.NAME_MAP).comment("Method by which party claim & force-load limits are calculated.","LARGEST: use the limits of the member with the largest limits","SUM: add up all the members' limits","OWNER: use the party owner's limits only","AVERAGE: use the average of all members' limits.");
BooleanValue REQUIRE_GAME_STAGE = CONFIG.getBoolean("require_game_stage", false).comment("If true, the player must have the 'ftbchunks_mapping' Game stage to be able to use the map and minimap.\nRequires KubeJS and/or Gamestages to be installed.");
BooleanValue LOCATION_MODE_OVERRIDE = CONFIG.getBoolean("location_mode_override", false).comment("If true, \"Location Visibility\" team settings are ignored, and all players can see each other anywhere on the map.");
BooleanValue OFFLINE_PROTECTION_ONLY = CONFIG.getBoolean("offline_protection_only", false).comment("If enabled and disable_protection = false enemy players will ONLY be able to damage your claimed chunks if you or your team mates are online.");
IntValue OFFLINE_PROTECTION_BUFFER = CONFIG.getInt("offline_protection_buffer", 30).comment("If offline_protection_only = true, the time in SECONDS after all members of a team log off, before chunk protection turns on. This setting is meant to discourage combat logging. Set to 0 to disable. Set to -1 for unlimited block breaking if offline_protection_only = true.");
IntValue MAX_DESTROY_BLOCKS_PER_HOUR = CONFIG.getInt("max_destroy_blocks_per_hour", 0).comment("If disable_protection = false, this many blocks can still be destroyed per hour be enemy players. 0 disables this.");
IntValue DESTROY_BLOCKS_COUNT_PERIOD = CONFIG.getInt("destroy_blocks_count_period", 300).comment("If max_destroy_blocks_per_hour > 0, the groups of time in seconds where the number of blocks broken are counted. Groups younger than an hour contribute to the total blocks broken. Groups older than an hour are removed.");
BooleanValue PROTECT_ENTITIES_OFFLINE_ONLY = CONFIG.getBoolean("protect_entities_offline_only", true).comment("Only protect the living entities listed in the living_entity_attack_blacklist tag when all team members are offline.");
BooleanValue PROTECT_NAMED_ENTITIES = CONFIG.getBoolean("protect_named_entities", false).comment("Protect entities that have a name tag.");
BooleanValue PROTECT_UNKNOWN_BLOCK_BREAKER = CONFIG.getBoolean("protect_unknown_block_breaker", true).comment("Protect blocks if the owner of the block breaker is not defined.");

static int getMaxClaimedChunks(FTBChunksTeamData playerData, ServerPlayer player) {
if (player != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,24 @@ public void setBypassProtection(UUID player, boolean bypass) {
* @return true to prevent the interaction, false to permit it
*/
public boolean protect(@Nullable Entity entity, InteractionHand hand, BlockPos pos, Protection protection, @Nullable Entity targetEntity) {
return protect(entity, hand, pos, protection, targetEntity, false);
}

/**
* Check if the intended interaction should be prevented from occurring.
*
* @param entity the entity performing the interaction
* @param hand the actor's hand
* @param pos the block position at which the action will be performed
* @param protection the type of protection being checked for
* @param targetEntity the entity being acted upon, if any (e.g. a painting, armor stand etc.)
* @param protectIfNullEntity if true, and entity = null, will return true
* @return true to prevent the interaction, false to permit it
*/
public boolean protect(@Nullable Entity entity, InteractionHand hand, BlockPos pos, Protection protection, @Nullable Entity targetEntity, boolean protectIfNullEntity) {
if (protectIfNullEntity && entity == null && FTBChunksWorldConfig.PROTECT_UNKNOWN_BLOCK_BREAKER.get()) {
return true;
}
if (!(entity instanceof ServerPlayer player) || FTBChunksWorldConfig.DISABLE_PROTECTION.get() || player.level == null) {
return false;
}
Expand Down Expand Up @@ -267,4 +285,8 @@ public void registerClaim(ChunkDimPos pos, ClaimedChunk chunk) {
public void unregisterClaim(ChunkDimPos pos) {
claimedChunks.remove(pos);
}

public Collection<FTBChunksTeamData> getAllTeamData() {
return teamData.values();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
*/
public class FTBChunksAPI {
public static final TagKey<Block> EDIT_WHITELIST_TAG = TagKey.create(Registry.BLOCK_REGISTRY, new ResourceLocation(FTBChunks.MOD_ID, "edit_whitelist"));
public static final TagKey<Block> EDIT_BLACKLIST_TAG = TagKey.create(Registry.BLOCK_REGISTRY, new ResourceLocation(FTBChunks.MOD_ID, "edit_blacklist"));
public static final TagKey<Block> INTERACT_WHITELIST_TAG = TagKey.create(Registry.BLOCK_REGISTRY, new ResourceLocation(FTBChunks.MOD_ID, "interact_whitelist"));
public static final TagKey<Item> RIGHT_CLICK_BLACKLIST_TAG = TagKey.create(Registry.ITEM_REGISTRY, new ResourceLocation(FTBChunks.MOD_ID, "right_click_blacklist"));
public static final TagKey<Item> RIGHT_CLICK_WHITELIST_TAG = TagKey.create(Registry.ITEM_REGISTRY, new ResourceLocation(FTBChunks.MOD_ID, "right_click_whitelist"));
public static final TagKey<EntityType<?>> ENTITY_INTERACT_WHITELIST_TAG = TagKey.create(Registry.ENTITY_TYPE_REGISTRY, new ResourceLocation(FTBChunks.MOD_ID, "entity_interact_whitelist"));
public static final TagKey<EntityType<?>> LIVING_ENTITY_ATTACK_BLACKLIST_TAG = TagKey.create(Registry.ENTITY_TYPE_REGISTRY, new ResourceLocation(FTBChunks.MOD_ID, "living_entity_attack_blacklist"));
public static final TagKey<EntityType<?>> NONLIVING_ENTITY_ATTACK_WHITELIST_TAG = TagKey.create(Registry.ENTITY_TYPE_REGISTRY, new ResourceLocation(FTBChunks.MOD_ID, "nonliving_entity_attack_whitelist"));

public static final TicketType<ChunkPos> FORCE_LOADED_TICKET = TicketType.create(FTBChunks.MOD_ID + ":force_loaded", Comparator.comparingLong(ChunkPos::toLong));
Expand Down
Loading