Add alternative ending

This commit is contained in:
ChaoticByte 2024-11-01 13:55:07 +01:00
parent 13e766c1bf
commit bd5f380091
No known key found for this signature in database
4 changed files with 107 additions and 2 deletions

View file

@ -3,6 +3,8 @@
This Minecraft mod allows you to prevent the world generator from generating new chunks past a defined limit.
You can set the limit by changing the gamerule `chunkGenerationLimit`.
This mod also adds an alternative ending. You can turn this off with `/gamerule truncatedAlternativeEnding false`.
Requires Fabric API!
## Known Incompatibilities

View file

@ -0,0 +1,35 @@
package net.chaoticbyte.truncated;
import com.mojang.serialization.Codec;
import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.predicate.entity.LootContextPredicate;
import net.minecraft.predicate.entity.LootContextPredicateValidator;
import net.minecraft.server.network.ServerPlayerEntity;
import java.util.Optional;
public class PlayerReachedLimitCriterion extends AbstractCriterion<PlayerReachedLimitCriterion.Conditions> {
public void trigger(ServerPlayerEntity player) {
this.trigger(player, conditions -> true);
}
// practically unnecessary boilerplate:
@Override
public Codec<Conditions> getConditionsCodec() {
return PlayerReachedLimitCriterion.Conditions.CODEC;
}
public record Conditions() implements AbstractCriterion.Conditions {
public static final Codec<PlayerReachedLimitCriterion.Conditions> CODEC = Codec.unit(new PlayerReachedLimitCriterion.Conditions());
@Override
public void validate(LootContextPredicateValidator validator) {}
@Override
public Optional<LootContextPredicate> player() {
return Optional.empty();
}
}
}

View file

@ -3,21 +3,43 @@ package net.chaoticbyte.truncated;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
import net.minecraft.advancement.criterion.Criteria;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameRules;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
public class Truncated implements ModInitializer {
public static final String MOD_ID = "truncated";
public static final GameRules.Key<GameRules.IntRule> CHUNK_GEN_LIMIT_KEY = GameRuleRegistry.register(
"chunkGenerationLimit", GameRules.Category.MISC, GameRuleFactory.createIntRule((28_000_000 / 16) - 1 ));
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
// gamerules
public static final GameRules.Key<GameRules.IntRule> CHUNK_GEN_LIMIT_KEY = GameRuleRegistry.register(
"chunkGenerationLimit",
GameRules.Category.MISC,
GameRuleFactory.createIntRule((28_000_000 / 16) - 1 )
);
public static final GameRules.Key<GameRules.BooleanRule> TRUNCATED_ALT_ENDING = GameRuleRegistry.register(
"truncatedAlternativeEnding",
GameRules.Category.MISC,
GameRuleFactory.createBooleanRule (true)
);
// advancement criterion
public static PlayerReachedLimitCriterion PLAYER_REACHED_LIMIT = Criteria.register(
MOD_ID + "/reached_limit",
new PlayerReachedLimitCriterion());
// variable temporary holding the server reference later
private static MinecraftServer server;
// get the limit set by the gamerule
public static int getLimit() {
return server.getGameRules().getInt(CHUNK_GEN_LIMIT_KEY);
}
@ -27,6 +49,30 @@ public class Truncated implements ModInitializer {
ServerLifecycleEvents.SERVER_STARTING.register(minecraftServer -> {
server = minecraftServer;
});
ServerTickEvents.START_WORLD_TICK.register(minecraftServer -> {
if (minecraftServer.getGameRules().getBoolean(TRUNCATED_ALT_ENDING)) {
float currentBlockLimit = getLimit() * 16;
java.util.List<net.minecraft.server.network.ServerPlayerEntity> playerEntitiesReachedEnd = new ArrayList<>();
minecraftServer.getPlayers().forEach(playerEntity -> {
if (!playerEntity.isSpectator()) {
Vec3d playerPos = playerEntity.getPos();
if (
playerPos.x > currentBlockLimit + 16
|| playerPos.x < -currentBlockLimit
|| playerPos.z > currentBlockLimit + 16
|| playerPos.z < -currentBlockLimit
) {
playerEntitiesReachedEnd.add(playerEntity);
}
}
});
// trigger the end credits for all players out of bounds
playerEntitiesReachedEnd.forEach(playerEntity -> {
PLAYER_REACHED_LIMIT.trigger(playerEntity); // trigger advancement
playerEntity.detachForDimensionChange(); // end credits
});
}
});
}
}

View file

@ -0,0 +1,22 @@
{
"parent": "minecraft:story/root",
"criteria": {
"reached_limit": {"conditions": {}, "trigger": "minecraft:truncated/reached_limit"}
},
"display": {
"announce_to_chat": true,
"description": {
"text": "You have traveled beyond the natural limits of this world (alternative ending)"
},
"frame": "goal",
"hidden": false,
"icon": {
"id": "minecraft:compass"
},
"title": {
"text": "The Limits of this World"
},
"show_toast": true
},
"requirements": [["reached_limit"]]
}