Skip to content
Merged

Dev #18

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
215 changes: 182 additions & 33 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ archives_base_name=ftb-team-bases
maven_group=dev.ftb.mods

#Deps
ftb_library_version=2101.1.20
ftb_teams_version=2101.1.7
ftb_library_version=2101.1.30
ftb_teams_version=2101.1.8
ftb_chunks_version=2101.1.13
curios_version=9.5.1+1.21.1

Expand Down
12 changes: 7 additions & 5 deletions src/main/java/dev/ftb/mods/ftbteambases/FTBTeamBases.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import dev.ftb.mods.ftbteambases.command.CommandUtils;
import dev.ftb.mods.ftbteambases.config.ClientConfig;
import dev.ftb.mods.ftbteambases.config.ServerConfig;
import dev.ftb.mods.ftbteambases.config.StartupConfig;
import dev.ftb.mods.ftbteambases.data.bases.BaseInstanceManager;
import dev.ftb.mods.ftbteambases.data.construction.BaseConstructionManager;
import dev.ftb.mods.ftbteambases.data.construction.RelocatorTracker;
Expand Down Expand Up @@ -76,6 +77,7 @@ public FTBTeamBases(IEventBus modBus) {
ModSounds.init(modBus);
ModArgumentTypes.init(modBus);

ConfigManager.getInstance().registerStartupConfig(StartupConfig.CONFIG, "startup");
ConfigManager.getInstance().registerServerConfig(ServerConfig.CONFIG, "server", false);
ConfigManager.getInstance().registerClientConfig(ClientConfig.CONFIG, "client");

Expand Down Expand Up @@ -119,7 +121,7 @@ private static void serverStarting(ServerStartingEvent event) {
}

private static void serverStarted(ServerStartedEvent event) {
ServerConfig.lobbyDimension().ifPresent(dim -> {
StartupConfig.lobbyDimension().ifPresent(dim -> {
// only override overworld default spawn pos if the lobby is actually in the overworld
if (dim.equals(OVERWORLD)) {
ServerLevel level = event.getServer().getLevel(OVERWORLD);
Expand Down Expand Up @@ -150,7 +152,7 @@ private static void onLevelLoad(LevelEvent.Load event) {
}
}

ServerConfig.lobbyDimension().ifPresent(rl -> {
StartupConfig.lobbyDimension().ifPresent(rl -> {
if (serverLevel.dimension().equals(rl)) {
maybeCreateLobbyFromStructure(serverLevel);
FTBChunksIntegration.maybeAutoClaimLobby(serverLevel);
Expand All @@ -170,7 +172,7 @@ private static void playerEnterServer(net.neoforged.neoforge.event.entity.player
private static void playerJoinLevel(EntityJoinLevelEvent event) {
if (event.getEntity() instanceof ServerPlayer player && event.getLevel() instanceof ServerLevel serverLevel) {
if (isFirstTimeConnecting(player, serverLevel)) {
ServerLevel destLevel = ServerConfig.lobbyDimension()
ServerLevel destLevel = StartupConfig.lobbyDimension()
.map(dim -> serverLevel.getServer().getLevel(dim))
.orElse(serverLevel);

Expand Down Expand Up @@ -204,7 +206,7 @@ private static void playerChangedDimension(PlayerEvent.PlayerChangedDimensionEve

private static void switchGameMode(ServerPlayer player, @Nullable ResourceKey<Level> oldDim, ResourceKey<Level> newDim) {
GameType lobbyGameMode = ServerConfig.LOBBY_GAME_MODE.get();
ResourceKey<Level> lobby = ServerConfig.lobbyDimension().orElse(OVERWORLD);
ResourceKey<Level> lobby = StartupConfig.lobbyDimension().orElse(OVERWORLD);

if (newDim.equals(lobby) && player.gameMode.getGameModeForPlayer() != lobbyGameMode && player.gameMode.getGameModeForPlayer() != GameType.CREATIVE) {
player.setGameMode(lobbyGameMode);
Expand Down Expand Up @@ -275,7 +277,7 @@ private static void onPlayerRespawn(PlayerRespawnPositionEvent event) {
MinecraftServer server = event.getEntity().getServer();
if (server != null) {
BaseInstanceManager mgr = BaseInstanceManager.get(server);
ServerLevel lobbyLvl = server.getLevel(ServerConfig.lobbyDimension().orElse(Level.OVERWORLD));
ServerLevel lobbyLvl = server.getLevel(StartupConfig.lobbyDimension().orElse(Level.OVERWORLD));
if (lobbyLvl != null) {
event.setDimensionTransition(new DimensionTransition(
lobbyLvl, Vec3.atCenterOf(mgr.getLobbySpawnPos()), Vec3.ZERO,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.ftb.mods.ftbteambases.block;

import dev.ftb.mods.ftbteambases.config.ServerConfig;
import dev.ftb.mods.ftbteambases.data.bases.BaseInstanceManager;
import dev.ftb.mods.ftbteambases.data.construction.BaseConstructionManager;
import dev.ftb.mods.ftbteambases.events.neoforge.TeamBasesPortalEvent;
Expand All @@ -15,6 +16,7 @@
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
Expand Down Expand Up @@ -110,4 +112,15 @@ public void animateTick(BlockState blockState, Level level, BlockPos pos, Random
level.addParticle(ParticleTypes.PORTAL, x, y, z, xo, yo, zo);
}
}

public static void checkForSpectator(Entity entity) {
// spectator mode players don't normally activate portals - see EntityMixin
if (entity instanceof Player player && player.isSpectator() && ServerConfig.ALLOW_LOBBY_SPECTATORS.get()) {
BlockPos pos = player.blockPosition().above();
BlockState blockState = player.level().getBlockState(pos);
if (blockState.getBlock() == ModBlocks.PORTAL.get()) {
blockState.entityInside(player.level(), pos, player);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public static void registerCommands(RegisterCommandsEvent event) {
.then(ArchiveCommand.register())
.then(PurgeCommand.register())
.then(SetLobbyPosCommand.register())
.then(RedoAutoclaimCommand.register())
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.ftb.mods.ftbteambases.command;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import dev.ftb.mods.ftbteambases.data.bases.BaseInstanceManager;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;

public class RedoAutoclaimCommand {
public static LiteralArgumentBuilder<CommandSourceStack> register() {
return Commands.literal("redo_autoclaim")
.requires(ctx -> ctx.hasPermission(2))
.executes(ctx -> {
BaseInstanceManager.get(ctx.getSource().getServer()).setAutoclaimNeeded(true);
ctx.getSource().sendSuccess(() -> Component.literal("Lobby autoclaiming will be redone on next lobby level load"), false);
return Command.SINGLE_SUCCESS;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import dev.ftb.mods.ftbteambases.config.ServerConfig;
import dev.ftb.mods.ftbteambases.config.StartupConfig;
import dev.ftb.mods.ftbteambases.data.bases.BaseInstanceManager;
import dev.ftb.mods.ftbteambases.util.MiscUtil;
import net.minecraft.commands.CommandSourceStack;
Expand All @@ -29,7 +30,7 @@ private static int setLobbyPos(CommandSourceStack source, BlockPos pos) {

source.sendSuccess(() -> Component.literal("lobby pos updated to " + MiscUtil.blockPosStr(pos)), false);

ServerConfig.lobbyDimension().ifPresent(dim -> {
StartupConfig.lobbyDimension().ifPresent(dim -> {
ServerLevel level = source.getServer().getLevel(dim);
if (level != null) {
level.setDefaultSpawnPos(pos, ServerConfig.LOBBY_PLAYER_YAW.get().floatValue());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package dev.ftb.mods.ftbteambases.config;

import dev.ftb.mods.ftblibrary.snbt.SNBTCompoundTag;
import dev.ftb.mods.ftblibrary.snbt.config.BaseValue;
import dev.ftb.mods.ftblibrary.snbt.config.SNBTConfig;
import dev.ftb.mods.ftbteambases.FTBTeamBases;
import net.minecraft.ResourceLocationException;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;

import java.util.ArrayList;
import java.util.List;

public class ResourceLocationListValue extends BaseValue<List<ResourceLocation>> {
private final String comment;

public ResourceLocationListValue(SNBTConfig parent, String key, List<ResourceLocation> defaultValue, String comment) {
super(parent, key, defaultValue);
this.comment = comment;
}

@Override
public void write(SNBTCompoundTag tag) {
ListTag list = new ListTag();
for (ResourceLocation rl : get()) {
list.add(StringTag.valueOf(rl.toString()));
}
tag.comment(key, comment);
tag.put(key, list);
}

@Override
public void read(SNBTCompoundTag tag) {
if (!tag.contains(key)) {
set(defaultValue);
return;
}
ListTag listTag = tag.getList(key, Tag.TAG_STRING);
List<ResourceLocation> result = new ArrayList<>();
for (Tag t : listTag) {
String value = t.getAsString();
if (value != null && !value.isBlank()) {
try {
result.add(ResourceLocation.parse(value));
} catch (ResourceLocationException e) {
FTBTeamBases.LOGGER.error("Invalid resource location in '{}': {}", key, value);
}
}
}
set(List.copyOf(result));
}
}
29 changes: 5 additions & 24 deletions src/main/java/dev/ftb/mods/ftbteambases/config/ServerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;

import java.util.List;
import java.util.Optional;

public interface ServerConfig {
Expand All @@ -35,6 +36,8 @@ public interface ServerConfig {
.comment("Base separation (in 512-block regions) when allocating regions for new bases in shared dimensions; the amount of clear space between the edges of two adjacent bases");
IntValue HOME_CMD_PERMISSION_LEVEL = GENERAL.addInt("home_cmd_permission_level", 0, 0, 4)
.comment("Permission level required to use the '/ftbteambases home' command; 0 = player, 2 = admin, 4 = server op");
BooleanValue ALLOW_LOBBY_SPECTATORS = GENERAL.addBoolean("allow_lobby_spectators", false)
.comment("If true, allow spectator-mode players to use the lobby portal");

SNBTConfig LOBBY = CONFIG.addGroup("lobby");
StringValue LOBBY_STRUCTURE_LOCATION = LOBBY.addString("lobby_structure_location", FTBTeamBases.rl("lobby").toString())
Expand All @@ -46,10 +49,6 @@ public interface ServerConfig {
EnumValue<GameType> LOBBY_GAME_MODE = LOBBY.addEnum("lobby_game_mode", GAME_TYPE_NAME_MAP)
.comment("The default game mode given to players when in the lobby.",
"Note that admin-mode players are free to change this.");
IntArrayValue LOBBY_SPAWN = LOBBY.addIntArray("lobby_spawn_pos", new int[]{ 0, 0, 0})
.comment("Position at which new players spawn. Only used if the lobby structure comes from a pregenerated region!");
StringValue LOBBY_DIMENSION = LOBBY.addString("lobby_dimension", "minecraft:overworld")
.comment("Dimension ID of the level in which the lobby is created. This *must* be a static pre-existing dimension, not a dynamically created one! New players will be automatically teleported to this dimension the first time they connect to the server. This setting should be defined in default config so the server has it before any levels are created - do NOT modify this on existing worlds!");
DoubleValue LOBBY_PLAYER_YAW = LOBBY.addDouble("lobby_player_yaw", 0.0, 0.0, 360.0)
.comment("Player Y-axis rotation when initially spawning in, or returning to, the lobby. (0 = south, 90 = west, 180 = north, 270 = east)");

Expand Down Expand Up @@ -83,7 +82,8 @@ public interface ServerConfig {
.comment("See 'use_custom_portal_y'.");

SNBTConfig AUTOCLAIMING = CONFIG.addGroup("autoclaiming")
.comment("Autoclaim lobby areas (FTB Chunks required)");
.comment("Autoclaim lobby areas (FTB Chunks required)",
"If you change any autoclaim settings after initial autoclaim is done, run '/ftbteambases redo_autoclaim'");
IntValue LOBBY_RADIUS = AUTOCLAIMING.addInt("lobby_radius", 0, 0, Integer.MAX_VALUE)
.comment("Radius in chunks for the lobby area to autoclaim",
"0 = autoclaiming disabled",
Expand All @@ -109,25 +109,6 @@ static Optional<ResourceLocation> lobbyLocation() {
}
}

static Optional<ResourceKey<Level>> lobbyDimension() {
try {
return Optional.of(ResourceKey.create(Registries.DIMENSION, ResourceLocation.parse(LOBBY_DIMENSION.get())));
} catch (ResourceLocationException ignored) {
FTBTeamBases.LOGGER.error("invalid dimension ID in config 'lobby_dimension': {}", ServerConfig.LOBBY_DIMENSION.get());
return Optional.empty();
}
}

static Optional<BlockPos> lobbyPos() {
int[] pos = ServerConfig.LOBBY_SPAWN.get();
if (pos.length == 3) {
return Optional.of(new BlockPos(pos[0], pos[1], pos[2]));
} else {
FTBTeamBases.LOGGER.error("invalid lobby spawn pos! expected 3 integers, got {}", pos.length);
return Optional.empty();
}
}

static int getNetherPortalYPos(Player player) {
return USE_CUSTOM_PORTAL_Y_POS.get() ? CUSTOM_PORTAL_Y_POS.get() : player.blockPosition().getY();
}
Expand Down
65 changes: 65 additions & 0 deletions src/main/java/dev/ftb/mods/ftbteambases/config/StartupConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package dev.ftb.mods.ftbteambases.config;

import dev.ftb.mods.ftblibrary.snbt.config.IntArrayValue;
import dev.ftb.mods.ftblibrary.snbt.config.SNBTConfig;
import dev.ftb.mods.ftblibrary.snbt.config.StringValue;
import dev.ftb.mods.ftbteambases.FTBTeamBases;
import net.minecraft.ResourceLocationException;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;

import java.util.List;
import java.util.Optional;

/**
* Startup configs are loaded immediately from the mod constructor.
* Use this for values that must be available before the server starts.
* These configs cannot be edited in-game and are not synced to clients.
*/
public interface StartupConfig {
SNBTConfig CONFIG = SNBTConfig.create(FTBTeamBases.MOD_ID + "-startup");

StringValue LOBBY_DIMENSION = CONFIG.addString("lobby_dimension", "minecraft:overworld")
.comment("Dimension ID of the level in which the lobby is created.",
"This *must* be a static pre-existing dimension, not a dynamically created one!",
"New players will be automatically teleported to this dimension the first time they connect.",
"WARNING: Do NOT modify this on existing worlds!");

ResourceLocationListValue ADDITIONAL_PREGEN_DIMENSIONS = CONFIG.add(new ResourceLocationListValue(
CONFIG,
"additional_pregen_dimensions",
List.of(),
"Additional dimensions to copy pregen files for on new world creation.\n" +
"Place MCA files in ftbteambases/pregen_initial/dimensions/<namespace>/<path>/region/"
));

IntArrayValue LOBBY_SPAWN = CONFIG.addIntArray("lobby_spawn_pos", new int[]{0, 0, 0})
.comment("Position at which new players spawn.",
"Only used if the lobby structure comes from a pregenerated region!");

static Optional<ResourceKey<Level>> lobbyDimension() {
try {
return Optional.of(ResourceKey.create(Registries.DIMENSION, ResourceLocation.parse(LOBBY_DIMENSION.get())));
} catch (ResourceLocationException ignored) {
FTBTeamBases.LOGGER.error("invalid dimension ID in config 'lobby_dimension': {}", LOBBY_DIMENSION.get());
return Optional.empty();
}
}

static List<ResourceLocation> additionalPregenDimensions() {
return ADDITIONAL_PREGEN_DIMENSIONS.get();
}

static Optional<BlockPos> lobbyPos() {
int[] pos = LOBBY_SPAWN.get();
if (pos.length == 3) {
return Optional.of(new BlockPos(pos[0], pos[1], pos[2]));
} else {
FTBTeamBases.LOGGER.error("invalid lobby spawn pos! expected 3 integers, got {}", pos.length);
return Optional.empty();
}
}
}
Loading