Cycle random stage themes every 50 jumps in the endless part and unload chunks far behind the player
This commit is contained in:
1 parent
d4465063d4
commit
05f2fcb9da
2 files changed
+51
-7
No files matched your search
@@ -5,11 +5,14 @@ import net.minestom.server.particle.Particle;
|
|||||||
import net.minestom.server.sound.SoundEvent;
|
import net.minestom.server.sound.SoundEvent;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abschnitte entlang des Fortschritts: einmal durch das komplette Spiel, von der Wiese über
|
* Abschnitte entlang des Fortschritts: einmal durch das komplette Spiel, von der Wiese über
|
||||||
* Untergrund, Nether und Stronghold bis ins End; ab Sprung 1000 geht es endlos weiter. Jeder Abschnitt hat eigene
|
* Untergrund, Nether und Stronghold bis ins End; ab Sprung 1000 geht es endlos weiter, alle 50 Sprünge
|
||||||
|
* mit einem zufälligen Thema aus diesen Abschnitten. Jeder Abschnitt hat eigene
|
||||||
* Blöcke und eine eigene Stimmung (Tageszeit, Partikel, Musik).
|
* Blöcke und eine eigene Stimmung (Tageszeit, Partikel, Musik).
|
||||||
*/
|
*/
|
||||||
public class BlockPalette {
|
public class BlockPalette {
|
||||||
@@ -61,23 +64,48 @@ public class BlockPalette {
|
|||||||
new Stage(850, "End", NIGHT, Particle.END_ROD, SoundEvent.MUSIC_END, List.of(
|
new Stage(850, "End", NIGHT, Particle.END_ROD, SoundEvent.MUSIC_END, List.of(
|
||||||
Block.END_STONE, Block.END_STONE, Block.END_STONE_BRICKS,
|
Block.END_STONE, Block.END_STONE, Block.END_STONE_BRICKS,
|
||||||
Block.PURPUR_BLOCK, Block.PURPUR_PILLAR, Block.OBSIDIAN
|
Block.PURPUR_BLOCK, Block.PURPUR_PILLAR, Block.OBSIDIAN
|
||||||
)),
|
|
||||||
// nach dem End endlos weiter mit einem neutralen Block
|
|
||||||
new Stage(1000, "Unendlich", NIGHT, null, SoundEvent.MUSIC_MENU, List.of(
|
|
||||||
Block.SMOOTH_QUARTZ
|
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ab hier endlos: alle ENDLESS_SEGMENT Sprünge ein zufälliges Thema aus den Abschnitten oben
|
||||||
|
private static final int ENDLESS_FROM = 1000;
|
||||||
|
private static final int ENDLESS_SEGMENT = 50;
|
||||||
|
private static final Map<Integer, Stage> endlessStages = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public static Stage stageAt(int index) {
|
public static Stage stageAt(int index) {
|
||||||
|
if(index >= ENDLESS_FROM) return endlessStage((index - ENDLESS_FROM) / ENDLESS_SEGMENT);
|
||||||
for(Stage stage : STAGES.reversed()) {
|
for(Stage stage : STAGES.reversed()) {
|
||||||
if(index >= stage.from()) return stage;
|
if(index >= stage.from()) return stage;
|
||||||
}
|
}
|
||||||
return STAGES.getFirst();
|
return STAGES.getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Der letzte Abschnitt geht endlos weiter. */
|
|
||||||
public static boolean isEndless(Stage stage) {
|
public static boolean isEndless(Stage stage) {
|
||||||
return stage == STAGES.getLast();
|
return stage.from() >= ENDLESS_FROM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thema eines endlosen Abschnitts. Fest an die Abschnittsnummer gebunden (gleiches Thema beim
|
||||||
|
* Weiterspielen) und nie zweimal dasselbe hintereinander. Zwischengespeichert, damit jeder
|
||||||
|
* Abschnitt genau ein Stage-Objekt hat (Abschnittswechsel werden per Identität erkannt).
|
||||||
|
*/
|
||||||
|
private static Stage endlessStage(int segment) {
|
||||||
|
return endlessStages.computeIfAbsent(segment, n -> {
|
||||||
|
Stage theme = themeOf(n);
|
||||||
|
return new Stage(ENDLESS_FROM + n * ENDLESS_SEGMENT, "Unendlich · " + theme.name(), theme.time(), theme.ambient(), theme.music(), theme.blocks());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Würfelt die Themen ab Abschnitt 0 der Reihe nach, damit „nie zweimal hintereinander“ sicher gilt. */
|
||||||
|
private static Stage themeOf(int segment) {
|
||||||
|
int previous = -1;
|
||||||
|
int pick = 0;
|
||||||
|
for(int n = 0; n <= segment; n++) {
|
||||||
|
pick = new Random(n * 31L + 7).nextInt(STAGES.size());
|
||||||
|
if(pick == previous) pick = (pick + 1) % STAGES.size();
|
||||||
|
previous = pick;
|
||||||
|
}
|
||||||
|
return STAGES.get(pick);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Block getRandom(int index, Random random) {
|
public static Block getRandom(int index, Random random) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import net.minestom.server.coordinate.Pos;
|
|||||||
import net.minestom.server.coordinate.Vec;
|
import net.minestom.server.coordinate.Vec;
|
||||||
import net.minestom.server.entity.ItemEntity;
|
import net.minestom.server.entity.ItemEntity;
|
||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
|
import net.minestom.server.instance.Chunk;
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
import net.minestom.server.instance.block.Block;
|
import net.minestom.server.instance.block.Block;
|
||||||
import net.minestom.server.network.packet.server.play.ParticlePacket;
|
import net.minestom.server.network.packet.server.play.ParticlePacket;
|
||||||
@@ -164,6 +165,7 @@ public class JumpGenerator {
|
|||||||
if(reachedCheckpoint > previous) {
|
if(reachedCheckpoint > previous) {
|
||||||
this.checkpoint = this.step(reachedCheckpoint).pos();
|
this.checkpoint = this.step(reachedCheckpoint).pos();
|
||||||
Progress.save(this.player.getUuid(), reachedCheckpoint);
|
Progress.save(this.player.getUuid(), reachedCheckpoint);
|
||||||
|
this.unloadChunksBehind();
|
||||||
this.player.playSound(CHECKPOINT_SOUND);
|
this.player.playSound(CHECKPOINT_SOUND);
|
||||||
this.player.showTitle(CHECKPOINT_TITLE);
|
this.player.showTitle(CHECKPOINT_TITLE);
|
||||||
this.player.sendPacket(new ParticlePacket(Particle.CRIT, this.checkpoint, this.checkpoint.add(0.5), 1.5f, 50));
|
this.player.sendPacket(new ParticlePacket(Particle.CRIT, this.checkpoint, this.checkpoint.add(0.5), 1.5f, 50));
|
||||||
@@ -200,6 +202,20 @@ public class JumpGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Strecke wandert immer in +z. Chunks hinter dem Checkpoint und außerhalb der Sichtweite
|
||||||
|
* werden nie wieder gebraucht (Reset und Rettung liegen davor): freigeben, sonst sammeln sich
|
||||||
|
* bei langen Läufen tausende an.
|
||||||
|
*/
|
||||||
|
private void unloadChunksBehind() {
|
||||||
|
int playerChunk = this.player.getPosition().blockZ() >> 4;
|
||||||
|
int checkpointChunk = this.checkpoint.blockZ() >> 4;
|
||||||
|
int keepFrom = Math.min(checkpointChunk, playerChunk - this.player.effectiveViewDistance()) - 1;
|
||||||
|
for(Chunk chunk : List.copyOf(this.world.getChunks())) {
|
||||||
|
if(chunk.getChunkZ() < keepFrom) this.world.unloadChunk(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ensureGenerated(int upTo, int stepTicks) {
|
private void ensureGenerated(int upTo, int stepTicks) {
|
||||||
int delay = 0;
|
int delay = 0;
|
||||||
while(this.generated() <= upTo) {
|
while(this.generated() <= upTo) {
|
||||||
|
|||||||
Reference in new issue
Block a user