Skip to content

Commit

Permalink
Bind modules to the game space
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugman76 committed Dec 3, 2024
1 parent d9052a8 commit 8fd8d9c
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 55 deletions.
13 changes: 12 additions & 1 deletion src/main/java/com/hugman/uhc/command/ModulesCommand.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.hugman.uhc.command;

import com.hugman.uhc.config.UHCGameConfig;
import com.hugman.uhc.game.ModuleManager;
import com.hugman.uhc.game.UHCAttachments;
import com.hugman.uhc.module.Module;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
Expand All @@ -19,6 +21,7 @@
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import xyz.nucleoid.plasmid.api.game.GameAttachment;
import xyz.nucleoid.plasmid.api.game.GameSpace;
import xyz.nucleoid.plasmid.api.game.GameSpaceManager;

Expand All @@ -44,7 +47,15 @@ public static boolean isSourceInUHC(ServerCommandSource source) {

private static int displayModules(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
ServerCommandSource source = context.getSource();
RegistryEntryList<Module> moduleEntries = ((UHCGameConfig) Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getMetadata().sourceConfig().value().config()).uhcConfig().value().modules();
// TODO: get modules by the current game space instead

var attachment = Objects.requireNonNull(GameSpaceManager.get().byWorld(source.getWorld())).getAttachment(UHCAttachments.MODULE_MANAGER);

if(attachment == null) {
throw NO_MODULES_ACTIVATED.create();
}

RegistryEntryList<Module> moduleEntries = attachment.modules();
if (moduleEntries.size() != 0) {
ScreenHandlerType<?> type = Registries.SCREEN_HANDLER.get(Identifier.of("generic_9x" + MathHelper.clamp(1, MathHelper.ceil((float) moduleEntries.size() / 9), 6)));
SimpleGui gui = new SimpleGui(type, source.getPlayer(), false);
Expand Down
29 changes: 0 additions & 29 deletions src/main/java/com/hugman/uhc/config/UHCGameConfig.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
package com.hugman.uhc.config;

import com.hugman.uhc.modifier.Modifier;
import com.hugman.uhc.modifier.ModifierType;
import com.hugman.uhc.module.Module;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.registry.entry.RegistryEntryList;
import net.minecraft.util.dynamic.Codecs;
import xyz.nucleoid.plasmid.api.game.common.config.WaitingLobbyConfig;

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

public record UHCGameConfig(
WaitingLobbyConfig players,
int teamSize,
Expand All @@ -24,25 +16,4 @@ public record UHCGameConfig(
Codecs.POSITIVE_INT.optionalFieldOf("team_size", 1).forGetter(UHCGameConfig::teamSize),
UHCConfig.ENTRY_CODEC.fieldOf("config").forGetter(UHCGameConfig::uhcConfig)
).apply(instance, UHCGameConfig::new));

public List<Modifier> getModifiers() {
List<Modifier> modifiers = new ArrayList<>();
for (var moduleEntry : uhcConfig.value().modules()) {
modifiers.addAll(moduleEntry.value().modifiers());
}
return modifiers;
}

public <V extends Modifier> List<V> getModifiers(ModifierType<V> type) {
//TODO: cache modules so it's quicker to sort by type
List<V> modifiers = new ArrayList<>();
for (var moduleEntry : uhcConfig.value().modules()) {
for (Modifier modifier : moduleEntry.value().modifiers()) {
if (modifier.getType() == type) {
modifiers.add((V) modifier);
}
}
}
return modifiers;
}
}
38 changes: 38 additions & 0 deletions src/main/java/com/hugman/uhc/game/ModuleManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.hugman.uhc.game;

import com.hugman.uhc.modifier.Modifier;
import com.hugman.uhc.modifier.ModifierType;
import com.hugman.uhc.module.Module;
import net.minecraft.registry.entry.RegistryEntryList;

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

public record ModuleManager(
RegistryEntryList<Module> modules
) {
public List<Modifier> getModifiers() {
List<Modifier> modifiers = new ArrayList<>();
for (var moduleEntry : modules) {
modifiers.addAll(moduleEntry.value().modifiers());
}
return modifiers;
}

public <V extends Modifier> List<V> getModifiers(ModifierType<V> type) {
//TODO: cache modules so it's quicker to sort by type
return filter(modules, type);
}

public static <V extends Modifier> List<V> filter(RegistryEntryList<Module> modules, ModifierType<V> type) {
List<V> modifiers = new ArrayList<>();
for (var moduleEntry : modules) {
for (Modifier modifier : moduleEntry.value().modifiers()) {
if (modifier.getType() == type) {
modifiers.add((V) modifier);
}
}
}
return modifiers;
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/hugman/uhc/game/UHCAttachments.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.hugman.uhc.game;

import com.hugman.uhc.UHC;
import xyz.nucleoid.plasmid.api.game.GameAttachment;

public class UHCAttachments {
public static final GameAttachment<ModuleManager> MODULE_MANAGER = GameAttachment.create(UHC.id("module_manager"));
}
18 changes: 11 additions & 7 deletions src/main/java/com/hugman/uhc/game/phase/UHCActive.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class UHCActive {
private final UHCSpawner spawnLogic;
private final UHCBar bar;
private final UHCSideBar sideBar;
private final ModuleManager moduleManager;

private long gameStartTick;
private long startInvulnerableTick;
Expand Down Expand Up @@ -93,6 +94,7 @@ private UHCActive(GameActivity activity, GameSpace gameSpace, ServerWorld world,
this.spawnLogic = new UHCSpawner(this.world);
this.bar = UHCBar.create(widgets, this.gameSpace);
this.sideBar = UHCSideBar.create(widgets, gameSpace);
this.moduleManager = new ModuleManager(config.uhcConfig().value().modules());
}

private void fillTeams() {
Expand Down Expand Up @@ -136,6 +138,8 @@ public static void start(GameSpace gameSpace, ServerWorld world, UHCGameConfig c
GlobalWidgets widgets = GlobalWidgets.addTo(activity);
UHCActive active = new UHCActive(activity, gameSpace, world, config, widgets);

gameSpace.setAttachment(UHCAttachments.MODULE_MANAGER, active.moduleManager);

activity.allow(GameRuleType.CRAFTING);
activity.deny(GameRuleType.PORTALS);
activity.deny(GameRuleType.PVP);
Expand Down Expand Up @@ -328,14 +332,14 @@ public void clearPlayer(ServerPlayerEntity player) {
}

public void refreshPlayerAttributes(ServerPlayerEntity player) {
for (PlayerAttributeModifier piece : this.config.getModifiers(ModifierType.PLAYER_ATTRIBUTE)) {
for (PlayerAttributeModifier piece : this.moduleManager.getModifiers(ModifierType.PLAYER_ATTRIBUTE)) {
piece.refreshAttribute(player);
}
player.networkHandler.sendPacket(new EntityAttributesS2CPacket(player.getId(), player.getAttributes().getTracked()));
}

public void applyPlayerEffects(ServerPlayerEntity player) {
for (PermanentEffectModifier piece : this.config.getModifiers(ModifierType.PERMANENT_EFFECT)) {
for (PermanentEffectModifier piece : this.moduleManager.getModifiers(ModifierType.PERMANENT_EFFECT)) {
piece.setEffect(player);
}
}
Expand Down Expand Up @@ -445,7 +449,7 @@ private void sendWarning(String s, Object... args) {
}

public void sendModuleListToChat() {
var moduleEntries = this.config.uhcConfig().value().modules();
var moduleEntries = this.moduleManager.modules();
if (moduleEntries.size() > 0) {
MutableText text = Text.literal("\n").append(Text.translatable("text.uhc.enabled_modules").formatted(Formatting.GOLD));
moduleEntries.forEach(moduleEntry -> {
Expand Down Expand Up @@ -487,15 +491,15 @@ private EventResult onPlayerDeath(ServerPlayerEntity player, DamageSource source
}

private EventResult onBlockBroken(ServerPlayerEntity playerEntity, ServerWorld world, BlockPos pos) {
for (TraversalBreakModifier piece : this.config.getModifiers(ModifierType.TRAVERSAL_BREAK)) {
for (TraversalBreakModifier piece : this.moduleManager.getModifiers(ModifierType.TRAVERSAL_BREAK)) {
piece.breakBlock(this.world, playerEntity, pos);
}
return EventResult.ALLOW;
}

private EventResult onExplosion(Explosion explosion, List<BlockPos> positions) {
positions.forEach(pos -> {
for (TraversalBreakModifier piece : this.config.getModifiers(ModifierType.TRAVERSAL_BREAK)) {
for (TraversalBreakModifier piece : this.moduleManager.getModifiers(ModifierType.TRAVERSAL_BREAK)) {
piece.breakBlock(this.world, explosion.getCausingEntity(), pos);
}
});
Expand All @@ -505,7 +509,7 @@ private EventResult onExplosion(Explosion explosion, List<BlockPos> positions) {
private DroppedItemsResult onMobLoot(LivingEntity livingEntity, List<ItemStack> itemStacks) {
boolean keepOld = true;
List<ItemStack> stacks = new ArrayList<>();
for (EntityLootModifier piece : this.config.getModifiers(ModifierType.ENTITY_LOOT)) {
for (EntityLootModifier piece : this.moduleManager.getModifiers(ModifierType.ENTITY_LOOT)) {
if (piece.test(livingEntity)) {
stacks.addAll(piece.getLoots(this.world, livingEntity));
if (piece.shouldReplace()) keepOld = false;
Expand All @@ -518,7 +522,7 @@ private DroppedItemsResult onMobLoot(LivingEntity livingEntity, List<ItemStack>
private DroppedItemsResult onBlockDrop(@Nullable Entity entity, ServerWorld world, BlockPos pos, BlockState state, List<ItemStack> itemStacks) {
boolean keepOld = true;
List<ItemStack> stacks = new ArrayList<>();
for (BlockLootModifier piece : this.config.getModifiers(ModifierType.BLOCK_LOOT)) {
for (BlockLootModifier piece : this.moduleManager.getModifiers(ModifierType.BLOCK_LOOT)) {
if (piece.test(state, world.getRandom())) {
piece.spawnExperience(world, pos);
stacks.addAll(piece.getLoots(world, pos, entity, entity instanceof LivingEntity ? ((LivingEntity) entity).getActiveItem() : ItemStack.EMPTY));
Expand Down
30 changes: 18 additions & 12 deletions src/main/java/com/hugman/uhc/map/ModuledChunkGenerator.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.hugman.uhc.map;

import com.hugman.uhc.config.UHCGameConfig;
import com.hugman.uhc.game.ModuleManager;
import com.hugman.uhc.modifier.ModifierType;
import com.hugman.uhc.modifier.PlacedFeaturesModifier;
import com.mojang.datafixers.util.Pair;
Expand Down Expand Up @@ -29,25 +30,28 @@
import net.minecraft.world.gen.StructureAccessor;
import net.minecraft.world.gen.chunk.*;
import net.minecraft.world.gen.chunk.placement.StructurePlacementCalculator;
import net.minecraft.world.gen.feature.PlacedFeature;
import net.minecraft.world.gen.noise.NoiseConfig;
import net.minecraft.world.gen.structure.Structure;
import org.jetbrains.annotations.Nullable;
import xyz.nucleoid.fantasy.util.ChunkGeneratorSettingsProvider;
import xyz.nucleoid.plasmid.api.game.world.generator.GameChunkGenerator;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class ModuledChunkGenerator extends GameChunkGenerator implements ChunkGeneratorSettingsProvider {
private final UHCGameConfig config;
private final List<PlacedFeature> placedFeatures;
private final long seed;
private final ChunkGenerator subGenerator;
private final ChunkGeneratorSettings settings;

public ModuledChunkGenerator(BiomeSource biomeSource, UHCGameConfig config, long seed, ChunkGenerator subGenerator, ChunkGeneratorSettings settings) {
public ModuledChunkGenerator(BiomeSource biomeSource, List<PlacedFeature> placedFeatures, long seed, ChunkGenerator subGenerator, ChunkGeneratorSettings settings) {
super(biomeSource);
this.config = config;
this.placedFeatures = placedFeatures;
this.seed = seed;
this.subGenerator = subGenerator;
this.settings = settings;
Expand All @@ -60,7 +64,13 @@ public static ModuledChunkGenerator of(UHCGameConfig config, long seed) {
if (subGenerator instanceof NoiseChunkGenerator generator) {
settings = generator.getSettings().value();
}
return new ModuledChunkGenerator(biomeSource, config, seed, subGenerator, settings);

List<PlacedFeature> placedFeatures = ModuleManager.filter(config.uhcConfig().value().modules(), ModifierType.PLACED_FEATURES).stream()
.flatMap(modifier -> modifier.features().stream())
.map(RegistryEntry::value)
.collect(Collectors.toList());

return new ModuledChunkGenerator(biomeSource, placedFeatures, seed, subGenerator, settings);
}

@Override
Expand All @@ -74,15 +84,11 @@ public void generateFeatures(StructureWorldAccess world, Chunk chunk, StructureA
ChunkRandom chunkRandom = new ChunkRandom(new Xoroshiro128PlusPlusRandom(this.seed));
long popSeed = chunkRandom.setPopulationSeed(world.getSeed(), blockPos.getX(), blockPos.getZ());

List<PlacedFeaturesModifier> placedFeaturesModifiers = this.config.getModifiers(ModifierType.PLACED_FEATURES);
int i = 0;
for (var modifier : placedFeaturesModifiers) {
for (var entry : modifier.features()) {
chunkRandom.setDecoratorSeed(popSeed, i++, 0);
Supplier<String> s = () -> entry.getKey().map(Object::toString).orElseGet(entry::toString);
world.setCurrentlyGeneratingStructureName(s);
entry.value().generate(world, this, chunkRandom, blockPos);
}
for (var placedFeature : this.placedFeatures) {
chunkRandom.setDecoratorSeed(popSeed, i++, 0);
world.setCurrentlyGeneratingStructureName(() -> "custom UHC feature");
placedFeature.generate(world, this, chunkRandom, blockPos);
}
world.setCurrentlyGeneratingStructureName(null);
this.subGenerator.generateFeatures(world, chunk, structureAccessor);
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/com/hugman/uhc/modifier/BlockLootModifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@
import java.util.List;
import java.util.Optional;

public record BlockLootModifier(boolean replace, RuleTest predicate, Optional<RegistryKey<LootTable>> lootTable,
int experience) implements Modifier {
public record BlockLootModifier(
boolean replace,
RuleTest predicate,
Optional<RegistryKey<LootTable>> lootTable,
int experience
) implements Modifier {
public static final MapCodec<BlockLootModifier> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.BOOL.optionalFieldOf("replace", true).forGetter(BlockLootModifier::replace),
RuleTest.TYPE_CODEC.fieldOf("target").forGetter(BlockLootModifier::predicate),
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/com/hugman/uhc/modifier/EntityLootModifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@
import java.util.List;
import java.util.Optional;

public record EntityLootModifier(boolean replace, RegistryEntryList<EntityType<?>> entities,
Optional<RegistryKey<LootTable>> lootTable) implements Modifier {
public record EntityLootModifier(
boolean replace,
RegistryEntryList<EntityType<?>> entities,
Optional<RegistryKey<LootTable>> lootTable
) implements Modifier {
public static final MapCodec<EntityLootModifier> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.BOOL.optionalFieldOf("replace", true).forGetter(EntityLootModifier::replace),
RegistryCodecs.entryList(RegistryKeys.ENTITY_TYPE).optionalFieldOf("entities", RegistryEntryList.empty()).forGetter(EntityLootModifier::entities),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.server.network.ServerPlayerEntity;

public record PermanentEffectModifier(RegistryEntry<StatusEffect> effect, int amplifier) implements Modifier {
public record PermanentEffectModifier(
RegistryEntry<StatusEffect> effect,
int amplifier
) implements Modifier {
public static final MapCodec<PermanentEffectModifier> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
StatusEffect.ENTRY_CODEC.fieldOf("effect").forGetter(PermanentEffectModifier::effect),
Codec.intRange(0, Integer.MAX_VALUE).optionalFieldOf("amplifier", 0).forGetter(PermanentEffectModifier::amplifier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
import org.jetbrains.annotations.Nullable;
import xyz.nucleoid.plasmid.api.util.BlockTraversal;

public record TraversalBreakModifier(RuleTest predicate, int amount, boolean includeLeaves) implements Modifier {
public record TraversalBreakModifier(
RuleTest predicate,
int amount,
boolean includeLeaves
) implements Modifier {
public static final MapCodec<TraversalBreakModifier> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
RuleTest.TYPE_CODEC.fieldOf("target").forGetter(module -> module.predicate),
Codec.intRange(0, Integer.MAX_VALUE).optionalFieldOf("amount", 128).forGetter(module -> module.amount),
Expand Down

0 comments on commit 8fd8d9c

Please sign in to comment.