Skip to content

Commit

Permalink
Merge pull request #263 from FTBTeam/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
desht authored Aug 25, 2023
2 parents 2b406ae + 667667b commit 4077037
Show file tree
Hide file tree
Showing 38 changed files with 174 additions and 911 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2001.2.0]

### Changed
* All cross-mod integration has been moved to the **FTB XMod Compat** mod
* This includes: FTB Ranks / Luckperms, Waystones, Game Stages (Forge only) and Common Protection API (Fabric only)

## [2001.1.5]

### Fixed
* Fixed cache invalidation issue when (un)claiming/loading chunks which caused client/server desync

## [2001.1.4]

### Fixed
Expand Down
7 changes: 0 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,6 @@ allprojects {
url "https://maven.architectury.dev/"
}

maven {
url "https://www.cursemaven.com"
content {
includeGroup "curse.maven"
}
}

maven {
url "https://maven.saps.dev/releases"
content {
Expand Down
5 changes: 0 additions & 5 deletions common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ dependencies {

modImplementation("dev.ftb.mods:ftb-library:${rootProject.ftb_library_version}") { transitive = false }
modImplementation("dev.ftb.mods:ftb-teams:${rootProject.ftb_teams_version}") { transitive = false }
modImplementation("dev.ftb.mods:ftb-ranks:${rootProject.ftb_ranks_version}") { transitive = false }
modImplementation("dev.latvian.mods:rhino:${rootProject.rhino_version}") { transitive = false }
modImplementation("dev.latvian.mods:kubejs:${rootProject.kubejs_version}") { transitive = false }

compileOnly 'net.luckperms:api:5.4'
}

def ENV = System.getenv()
Expand Down
10 changes: 2 additions & 8 deletions common/src/main/java/dev/ftb/mods/ftbchunks/FTBChunks.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import dev.architectury.event.EventResult;
import dev.architectury.event.events.common.*;
import dev.architectury.hooks.level.entity.PlayerHooks;
import dev.architectury.platform.Platform;
import dev.architectury.registry.registries.Registrar;
import dev.architectury.registry.registries.RegistrarManager;
import dev.architectury.utils.Env;
Expand All @@ -20,9 +19,8 @@
import dev.ftb.mods.ftbchunks.data.ClaimExpirationManager;
import dev.ftb.mods.ftbchunks.data.ClaimedChunkImpl;
import dev.ftb.mods.ftbchunks.data.ClaimedChunkManagerImpl;
import dev.ftb.mods.ftbchunks.integration.ftbranks.FTBRanksIntegration;
import dev.ftb.mods.ftbchunks.integration.stages.StageHelper;
import dev.ftb.mods.ftbchunks.net.*;
import dev.ftb.mods.ftblibrary.integration.stages.StageHelper;
import dev.ftb.mods.ftblibrary.math.ChunkDimPos;
import dev.ftb.mods.ftblibrary.math.MathUtils;
import dev.ftb.mods.ftblibrary.math.XZ;
Expand Down Expand Up @@ -132,10 +130,6 @@ public FTBChunks() {
TickEvent.SERVER_POST.register(this::serverTickPost);
TickEvent.PLAYER_POST.register(this::playerTickPost);

if (Platform.isModLoaded("ftbranks")) {
FTBRanksIntegration.registerEvents();
}

EnvExecutor.runInEnv(Env.CLIENT, () -> FTBChunksClient.INSTANCE::init);
}

Expand Down Expand Up @@ -399,7 +393,7 @@ private void playerCloned(ServerPlayer oldPlayer, ServerPlayer newPlayer, boolea
private void playerChangedDimension(ServerPlayer serverPlayer, ResourceKey<Level> oldLevel, ResourceKey<Level> newLevel) {
LongRangePlayerTracker.INSTANCE.stopTracking(serverPlayer);

StageHelper.INSTANCE.get().sync(serverPlayer);
StageHelper.INSTANCE.getProvider().sync(serverPlayer);
}

private void teamConfig(TeamCollectPropertiesEvent event) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package dev.ftb.mods.ftbchunks;

import dev.ftb.mods.ftbchunks.api.ChunkTeamData;
import dev.ftb.mods.ftbchunks.api.ProtectionPolicy;
import dev.ftb.mods.ftbchunks.data.AllyMode;
import dev.ftb.mods.ftbchunks.data.ChunkTeamDataImpl;
import dev.ftb.mods.ftbchunks.data.ForceLoadMode;
import dev.ftb.mods.ftbchunks.data.PartyLimitMode;
import dev.ftb.mods.ftbchunks.integration.PermissionsHelper;
import dev.ftb.mods.ftbchunks.integration.stages.StageHelper;
import dev.ftb.mods.ftbchunks.util.DimensionFilter;
import dev.ftb.mods.ftblibrary.config.NameMap;
import dev.ftb.mods.ftblibrary.integration.stages.StageHelper;
import dev.ftb.mods.ftblibrary.snbt.config.*;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
Expand All @@ -26,6 +27,7 @@ public interface FTBChunksWorldConfig {
StringListValue CLAIM_DIMENSION_BLACKLIST = CONFIG.addStringList("claim_dimension_blacklist", Collections.emptyList()).comment("Dimension ID's where chunks may not be claimed. Add \"minecraft:the_end\" to this list if you want to disable chunk claiming in The End, or \"othermod:*\" to disable chunk claiming in *all* dimensions added by \"othermod\"");
StringListValue CLAIM_DIMENSION_WHITELIST = CONFIG.addStringList("claim_dimension_whitelist", Collections.emptyList()).comment("Dimension ID's where chunks may be claimed. If non-empty, chunks may be claimed *only* in these dimensions (and the dimension is not in \"claim_dimension_blacklist\"). Same syntax as for \"claim_dimension_blacklist\".");
BooleanValue NO_WILDERNESS = CONFIG.addBoolean("no_wilderness", false).comment("Requires you to claim chunks in order to edit and interact with blocks");
StringListValue NO_WILDERNESS_DIMENSIONS = CONFIG.addStringList("no_wilderness_dimensions", Collections.emptyList()).comment("Dimension ID's where the no_wilderness rule is enforced - building is only allowed in claimed chunks. If this is non-empty, it overrides the 'no_wilderness' setting.");
BooleanValue FORCE_DISABLE_MINIMAP = CONFIG.addBoolean("force_disable_minimap", false).comment("Minimap for clients connecting to this server will be disabled");
DoubleValue MAX_IDLE_DAYS_BEFORE_UNCLAIM = CONFIG.addDouble("max_idle_days_before_unclaim", 0D, 0D, 3650D).comment("Maximum time (in real-world days) where if no player in a team logs in, the team automatically loses their claims.", "Prevents chunks being claimed indefinitely by teams who no longer play.","Default of 0 means no automatic loss of claims.");
DoubleValue MAX_IDLE_DAYS_BEFORE_UNFORCE = CONFIG.addDouble("max_idle_days_before_unforce", 0D, 0D, 3650D).comment("Maximum time (in real-world days) where if no player in a team logs in, any forceloaded chunks owned by the team are no longer forceloaded.", "Prevents chunks being forceloaded indefinitely by teams who no longer play.","Default of 0 means no automatic loss of forceloading.");
Expand All @@ -36,38 +38,40 @@ public interface FTBChunksWorldConfig {
EnumValue<PartyLimitMode> PARTY_LIMIT_MODE = CONFIG.addEnum("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.addBoolean("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.addBoolean("location_mode_override", false).comment("If true, \"Location Visibility\" team settings are ignored, and all players can see each other anywhere on the map.");
IntValue MAX_PREVENTED_LOG_AGE = CONFIG.addInt("max_prevented_log_age", 7, 1, Integer.MAX_VALUE).comment("Maximum time in days to keep logs of prevented fakeplayer access to a team's claims.");

static int getMaxClaimedChunks(ChunkTeamDataImpl playerData, ServerPlayer player) {
static int getMaxClaimedChunks(ChunkTeamData playerData, ServerPlayer player) {
if (player != null) {
return PermissionsHelper.getInstance().getMaxClaimedChunks(player, MAX_CLAIMED_CHUNKS.get()) + playerData.getExtraClaimChunks();
return PermissionsHelper.getMaxClaimedChunks(player, MAX_CLAIMED_CHUNKS.get()) + playerData.getExtraClaimChunks();
}

return MAX_CLAIMED_CHUNKS.get() + playerData.getExtraClaimChunks();
}

static int getMaxForceLoadedChunks(ChunkTeamDataImpl playerData, ServerPlayer player) {
static int getMaxForceLoadedChunks(ChunkTeamData playerData, ServerPlayer player) {
if (player != null) {
return PermissionsHelper.getInstance().getMaxForceLoadedChunks(player, MAX_FORCE_LOADED_CHUNKS.get()) + playerData.getExtraForceLoadChunks();
return PermissionsHelper.getMaxForceLoadedChunks(player, MAX_FORCE_LOADED_CHUNKS.get()) + playerData.getExtraForceLoadChunks();
}

return MAX_FORCE_LOADED_CHUNKS.get() + playerData.getExtraForceLoadChunks();
}

static boolean canPlayerOfflineForceload(ServerPlayer player) {
// note: purely checking the player's own permission here; not interested in server defaults or party data
return player != null && PermissionsHelper.getInstance().getChunkLoadOffline(player, false);
return player != null && PermissionsHelper.getChunkLoadOffline(player, false);
}

static boolean noWilderness(ServerPlayer player) {
if (player != null) {
return PermissionsHelper.getInstance().getNoWilderness(player, NO_WILDERNESS.get());
return DimensionFilter.isNoWildernessDimension(player.level().dimension())
|| PermissionsHelper.getNoWilderness(player, NO_WILDERNESS.get());
}

return NO_WILDERNESS.get();
}

static boolean playerHasMapStage(Player player) {
return !REQUIRE_GAME_STAGE.get() || StageHelper.INSTANCE.get().has(player, "ftbchunks_mapping");
return !REQUIRE_GAME_STAGE.get() || StageHelper.getInstance().getProvider().has(player, "ftbchunks_mapping");
}

static boolean shouldShowMinimap(Player player) {
Expand Down
10 changes: 10 additions & 0 deletions common/src/main/java/dev/ftb/mods/ftbchunks/api/ChunkTeamData.java
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,14 @@ public interface ChunkTeamData {
* @return the last login time for this team.
*/
long getLastLoginTime();

/**
* If the given player is an online player, update the team data based on their offline forceloading permissions.
* Intended for use by external permission mods such as FTB Ranks; call this when permissions change.
* <p>
* If the given player is not currently online or not a member of this team, this is a no-op.
*
* @param playerId ID of the player to check
*/
void checkMemberForceLoading(UUID playerId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import dev.architectury.event.events.client.*;
import dev.architectury.hooks.client.screen.ScreenAccess;
import dev.architectury.injectables.annotations.ExpectPlatform;
import dev.architectury.platform.Platform;
import dev.architectury.registry.ReloadListenerRegistry;
import dev.architectury.registry.client.keymappings.KeyMappingRegistry;
import dev.ftb.mods.ftbchunks.ColorMapLoader;
Expand All @@ -30,7 +29,6 @@
import dev.ftb.mods.ftbchunks.client.map.*;
import dev.ftb.mods.ftbchunks.client.map.color.ColorUtils;
import dev.ftb.mods.ftbchunks.client.mapicon.*;
import dev.ftb.mods.ftbchunks.integration.waystones.WaystonesIntegration;
import dev.ftb.mods.ftbchunks.net.PartialPackets;
import dev.ftb.mods.ftbchunks.net.SendGeneralDataPacket.GeneralChunkData;
import dev.ftb.mods.ftblibrary.config.StringConfig;
Expand Down Expand Up @@ -172,10 +170,6 @@ public void init() {
// RefreshMinimapIconsEvent.EVENT.register(this::refreshMinimapIcons);
ClientReloadShadersEvent.EVENT.register(this::reloadShaders);
registerPlatform();

if (Platform.isModLoaded("waystones")) {
WaystonesIntegration.initClient();
}
}

private void registerKeys() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dev.ftb.mods.ftbchunks.data;

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import dev.architectury.hooks.level.entity.PlayerHooks;
import dev.ftb.mods.ftbchunks.FTBChunks;
import dev.ftb.mods.ftbchunks.FTBChunksExpected;
Expand Down Expand Up @@ -27,6 +29,7 @@
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
Expand Down Expand Up @@ -64,6 +67,8 @@ public class ChunkTeamDataImpl implements ChunkTeamData {
private Collection<ClaimedChunkImpl> claimedChunkCache;
private Collection<ClaimedChunkImpl> forcedChunkCache;

private final Map<UUID,PreventedAccess> preventedAccess = new HashMap<>();

public ChunkTeamDataImpl(ClaimedChunkManagerImpl manager, Path file, Team team) {
this.manager = manager;
this.file = file;
Expand Down Expand Up @@ -96,7 +101,7 @@ public Path getFile() {
public TeamManager getTeamManager() {
return manager.getTeamManager();
}

@Override
public Team getTeam() {
return team;
Expand Down Expand Up @@ -354,6 +359,12 @@ public SNBTCompoundTag serializeNBT() {
tag.put("member_data", memberTag);
}

if (!preventedAccess.isEmpty()) {
SNBTCompoundTag p = new SNBTCompoundTag();
preventedAccess.forEach((id, element) -> p.put(id.toString(), PreventedAccess.CODEC.encodeStart(NbtOps.INSTANCE, element).result().orElseThrow()));
tag.put("prevented_access", p);
}

return tag;
}

Expand Down Expand Up @@ -391,6 +402,15 @@ public void deserializeNBT(CompoundTag tag) {
e.printStackTrace();
}
}

preventedAccess.clear();
if (tag.contains("prevented_access")) {
CompoundTag p = tag.getCompound("prevented_access");
for (String key : p.getAllKeys()) {
preventedAccess.put(UUID.fromString(key), PreventedAccess.CODEC.parse(NbtOps.INSTANCE, p.getCompound(key)).result().orElseThrow());
}
prunePreventedLog();
}
}

@Override
Expand Down Expand Up @@ -419,17 +439,17 @@ public int getExtraForceLoadChunks() {
return extraForceLoadChunks;
}

public void setForceLoadMember(UUID id, boolean val) {
long oldForceCount = memberData.values().stream().filter(TeamMemberData::isOfflineForceLoader).count();
getTeamMemberData(id).setOfflineForceLoader(val);
long newForceCount = memberData.values().stream().filter(TeamMemberData::isOfflineForceLoader).count();

if (oldForceCount != newForceCount) {
FTBChunks.LOGGER.debug("team {}: set force load member {} = {}", team.getId(), id, val);
markDirty();
canForceLoadChunks = null;
manager.clearForceLoadedCache();
public boolean setForceLoadMember(UUID id, boolean val) {
if (val == getTeamMemberData(id).isOfflineForceLoader()) {
return false;
}

getTeamMemberData(id).setOfflineForceLoader(val);
FTBChunks.LOGGER.debug("team {}: set force load member {} = {}", team.getId(), id, val);
markDirty();
canForceLoadChunks = null;
manager.clearForceLoadedCache();
return true;
}

@NotNull
Expand Down Expand Up @@ -653,7 +673,7 @@ public void deleteMemberData(UUID playerId) {

private boolean hasChunkChanged(ClaimedChunkImpl chunk) {
String s = chunk == null ? "-" : chunk.getTeamData().getTeamId().toString();
if (lastChunkID.equals(s)) {
if (!lastChunkID.equals(s)) {
lastChunkID = s;
return true;
}
Expand All @@ -680,4 +700,42 @@ public void clearClaimCaches() {
claimedChunkCache = null;
forcedChunkCache = null;
}

@Override
public void checkMemberForceLoading(UUID playerId) {
if (isTeamMember(playerId)) {
ServerPlayer player = manager.getMinecraftServer().getPlayerList().getPlayer(playerId);
if (player != null && setForceLoadMember(playerId, FTBChunksWorldConfig.canPlayerOfflineForceload(player))) {
updateLimits();
}
}
}

public void logPreventedAccess(ServerPlayer player, long when) {
preventedAccess.put(player.getUUID(), new PreventedAccess(player.getGameProfile().getName(), when));
markDirty();
}

private void prunePreventedLog() {
Set<UUID> toRemove = new HashSet<>();
long now = System.currentTimeMillis();
long max = FTBChunksWorldConfig.MAX_PREVENTED_LOG_AGE.get() * 86400L * 1000L;
preventedAccess.forEach((id, el) -> {
if (now - el.when() > max) {
toRemove.add(id);
}
});
if (!toRemove.isEmpty()) {
toRemove.forEach(preventedAccess::remove);
markDirty();
}
}

private record PreventedAccess(String name, long when) {
public static final Codec<PreventedAccess> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.STRING.fieldOf("name").forGetter(PreventedAccess::name),
Codec.LONG.fieldOf("when").forGetter(PreventedAccess::when)
).apply(instance, PreventedAccess::new)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public MutableComponent getMessage() {
public void setClaimedTime(long t) {
time = t;
teamData.getManager().clearForceLoadedCache();
teamData.clearClaimCaches();
sendUpdateToAll();
}

Expand All @@ -92,8 +93,13 @@ public boolean isActuallyForceLoaded() {
}

public void setForceLoadedTime(long time) {
if (forceLoaded == time) {
return;
}

forceLoaded = time;
teamData.getManager().clearForceLoadedCache();
teamData.clearClaimCaches();
sendUpdateToAll();

ServerLevel level = teamData.getManager().getMinecraftServer().getLevel(pos.dimension());
Expand Down Expand Up @@ -137,6 +143,7 @@ public void unload(CommandSourceStack source) {
if (isForceLoaded()) {
setForceLoadedTime(0L);
ClaimedChunkEvent.AFTER_UNLOAD.invoker().after(source, this);
teamData.clearClaimCaches();
teamData.markDirty();
forceLoadExpiryTime = 0L;
}
Expand All @@ -148,6 +155,7 @@ public void unclaim(CommandSourceStack source, boolean sync) {

teamData.getManager().unregisterClaim(pos);
ClaimedChunkEvent.AFTER_UNCLAIM.invoker().after(source, this);
teamData.clearClaimCaches();
teamData.markDirty();

if (sync) {
Expand Down Expand Up @@ -199,4 +207,5 @@ public static ClaimedChunkImpl deserializeNBT(ChunkTeamDataImpl data, ResourceKe
chunk.forceLoadExpiryTime = tag.getLong("expiry_time");
return chunk;
}

}
Loading

0 comments on commit 4077037

Please sign in to comment.