Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01a82c3c93 | ||
|
|
f23f741a9d | ||
|
|
4714c69255 | ||
|
|
c03e5d8555 | ||
|
|
9abf6bbea7 | ||
|
|
9c09664778 | ||
|
|
87f11f6127 | ||
|
|
c04cd78ae9 | ||
|
|
7ae99a12a8 |
+25
-2
@@ -6,9 +6,22 @@ Ce journal suit les **versions du modpack**. Lorsqu'un seul module change, sa ve
|
||||
- Depuis `26.2.0-alpha.6`, le pack et les modules ont des versions indépendantes. I Like To Move It et Only Fun deviennent les cinquième et sixième modules actifs dans l'alpha 46.
|
||||
- Les versions ci-dessous ont été reconstituées à partir des JAR archivés, des packs locaux et du code source actuel. Les dates n'étant pas enregistrées de manière fiable, elles ne sont pas inventées.
|
||||
|
||||
## `26.2.0-alpha.217`
|
||||
## `26.2.0-alpha.219`
|
||||
|
||||
Modules modifiés : **Red-Stoner `0.0.0-alpha.11`**, **Only Fun `0.0.0-alpha.25`** et **Sanctuary `0.0.0-alpha.121`**. Les sept autres modules conservent leur version issue de l'alpha.216.
|
||||
Modules modifiés : **Sanctuary `0.0.0-alpha.122`**, **I Like To Move It `0.0.0-alpha.16`** et **Ambiance `0.0.0-alpha.21`**. Les sept autres modules conservent leur version issue de l'alpha.218.
|
||||
|
||||
- ajoute `sanctuary:alpha`, une île Minecraft Indev finie de 128 × 128 × 64 blocs, déterministe par seed, avec plages, cavernes, minerais, eau, lave, végétation et maison de départ historique ;
|
||||
- borne le monde par un fond en bedrock et un anneau de barrières, sans placement au-delà de X/Z −64…63, et expose les positions stables de la résidence et de l'arrivée sûre via l'API publique de Sanctuary ;
|
||||
- ajoute la dimension, son biome, son type et ses réglages aux profils Sanctuary et Overworld, tout en conservant la migration `portals:alpha` vers `sanctuary:alpha` ;
|
||||
- active la route de portail v2 en cobblestone moussue, cadre 4 × 5 et intérieur 2 × 3, avec validation serveur, refus si la dimension manque, paire persistante, déliaison à la casse et arrivée distante hors de la maison ;
|
||||
- compose localement les packs officiels Golden Days Base puis Alpha uniquement dans `sanctuary:alpha`, restaure exactement la pile précédente à la sortie ou déconnexion et laisse les textures vanilla fonctionner si les ZIP manquent ;
|
||||
- ne distribue aucun asset Golden Days dans les JAR, Packwiz ou `.mrpack`, documente les liens et la licence officiels, et n'impose aucun fichier au serveur dédié ;
|
||||
- ajoute les traductions FR/EN/RU et des tests déterministes pour le générateur, le portail et la composition des packs ;
|
||||
- conserve Sanctuary data v11/protocole 22, I Like To Move It data v3/protocole 5 et Ambiance data v2/protocole 6, sans réinitialisation de sauvegarde.
|
||||
|
||||
## `26.2.0-alpha.218`
|
||||
|
||||
Modules modifiés : **Red-Stoner `0.0.0-alpha.11`**, **Only Fun `0.0.0-alpha.25`** et **Sanctuary `0.0.0-alpha.121`**. Les sept autres modules conservent leur version issue de l'alpha.217.
|
||||
|
||||
- ajoute `redstoner:storage_terminal`, une demi-dalle verticale de huit pixels qui se pose uniquement sur la face horizontale d’un coffre, coffre piégé ou baril ;
|
||||
- découvre sans charger de chunk les conteneurs adjacents par face, verticalement compris, et refuse clairement tout réseau qui dépasse 128 blocs physiques ;
|
||||
@@ -18,6 +31,16 @@ Modules modifiés : **Red-Stoner `0.0.0-alpha.11`**, **Only Fun `0.0.0-alpha.25`
|
||||
- ajoute les traductions FR/EN/RU, les ressources bloc/item/loot/recette et des tests déterministes de topologie, pagination, agrégation et transferts ;
|
||||
- conserve les données Red-Stoner v3, Only Fun v2 et Sanctuary v11 ; seul le protocole réseau Red-Stoner passe de 5 à 6, sans nouveau monde ni réinitialisation des sauvegardes.
|
||||
|
||||
## `26.2.0-alpha.217`
|
||||
|
||||
Module modifié : **Ambiance `0.0.0-alpha.20`**. Les neuf autres modules conservent leur version issue de l'alpha.216.
|
||||
|
||||
- corrige la hauteur trop grave et la vitesse trop lente du disque blanc en compensant la cadence du flux AAC YouTube par un facteur OpenAL exact de `4/3` ;
|
||||
- réapplique cette hauteur pendant toute la lecture afin qu’aucune mise à jour du canal audio ne la ramène à la valeur ralentie ;
|
||||
- valide la correction sur le lien signalé en comparant vingt secondes décodées par Lavaplayer au flux AAC direct, puis conserve les tests PCM 48 kHz et de niveau sonore ;
|
||||
- conserve les données Ambiance v2, le protocole réseau 6, les IDs et les sauvegardes existantes ;
|
||||
- distribue Ambiance `0.0.0-alpha.20` dans Packwiz et le `.mrpack` partagé client/serveur, sans exiger de nouveau monde ni réinitialiser les sauvegardes.
|
||||
|
||||
## `26.2.0-alpha.216`
|
||||
|
||||
Module modifié : **Ambiance `0.0.0-alpha.19`**. Les neuf autres modules conservent leur version issue de l'alpha.215.
|
||||
|
||||
@@ -22,11 +22,15 @@ Licence : **GNU GPL 3.0 or Later** (`GPL-3.0-or-later`)
|
||||
|
||||
Les descriptions FR/EN/RU sont déclarées dans chaque `fabric.mod.json` et dans les fichiers de langue. Les images fournies servent d'icônes Fabric de leur module.
|
||||
|
||||
Version courante du pack distribué : **`26.2.0-alpha.217`**. Cette release distribue Red-Stoner **`0.0.0-alpha.11`**, Only Fun **`0.0.0-alpha.25`** et Sanctuary **`0.0.0-alpha.121`** ; les sept autres modules conservent leur version issue de l'alpha.216.
|
||||
Version courante du pack distribué : **`26.2.0-alpha.219`**. Cette release distribue Sanctuary **`0.0.0-alpha.122`**, I Like To Move It **`0.0.0-alpha.16`** et Ambiance **`0.0.0-alpha.21`** ; les sept autres modules conservent leur version issue de l'alpha.218.
|
||||
|
||||
La migration [CANA-01 à CANA-09](CANAPLIA.md) porte Canaplia vers Minecraft 26.2. It's Alive **`0.0.0-alpha.35`** enregistre les seize familles, les découvertes, hybridations, résines, effets serveur et le Livre interdit personnel, partageable temporairement sur un pupitre. Ambiance **`0.0.0-alpha.14`** compose les profils visuels bornés avec ses réglages d'accessibilité, et Only Fun **`0.0.0-alpha.21`** exclut explicitement Canaplia et les raccourcis de progression du Shop.
|
||||
|
||||
L’alpha.217 ajoute le terminal de stockage Red-Stoner : cette demi-dalle verticale se fixe sur un coffre, un coffre piégé ou un baril et donne accès, par pages défilantes de 54 types, à un réseau contigu borné à 128 conteneurs chargés. Les retraits et dépôts sont validés par le serveur, les composants d’items restent strictement séparés et le terminal endgame est exclu du Shop, du Black Market et des récompenses Only Fun.
|
||||
L’alpha.219 porte l'île finie Minecraft Indev dans `sanctuary:alpha` : 128 × 128 × 64 blocs déterministes, plages, cavernes, minerais, fluides, végétation et maison historique, le tout borné sans chunks parasites. Le cadre 4 × 5 en cobblestone moussue est maintenant actif et crée une paire persistante à une arrivée sûre hors de la maison. Ambiance peut enfin composer localement Golden Days Base puis Alpha uniquement dans cette dimension, sans redistribuer leurs textures et en restaurant exactement la pile précédente. Voir le [contrat Alpha](sanctuary/ALPHA.md), le [contrat des portails](iliketomoveit/PORTALS.md) et le [guide Golden Days](ambiance/GOLDEN_DAYS.md).
|
||||
|
||||
L’alpha.218 ajoute le terminal de stockage Red-Stoner : cette demi-dalle verticale se fixe sur un coffre, un coffre piégé ou un baril et donne accès, par pages défilantes de 54 types, à un réseau contigu borné à 128 conteneurs chargés. Les retraits et dépôts sont validés par le serveur, les composants d’items restent strictement séparés et le terminal endgame est exclu du Shop, du Black Market et des récompenses Only Fun.
|
||||
|
||||
L’alpha.217 corrige définitivement la hauteur trop grave du disque blanc : la cadence AAC mesurée sur la vidéo signalée est compensée par un facteur OpenAL exact de 4/3, maintenu pendant toute la lecture.
|
||||
|
||||
L’alpha.216 corrige la lecture lente et dégradée du disque blanc : les quatre tampons PCM initiaux de Minecraft sont maintenant remplis continûment à 48 kHz, avec une vitesse OpenAL normale, au lieu d’être majoritairement complétés par du silence. Les packs Modrinth, Prism et Packwiz sont mis à jour sans exiger de nouveau monde ni réinitialiser les sauvegardes.
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# Textures historiques Golden Days dans Alpha
|
||||
|
||||
Ambiance peut charger les packs officiels Golden Days uniquement pendant que
|
||||
le client se trouve dans `sanctuary:alpha`. Aucun fichier, texture ou dérivé de
|
||||
Golden Days n'est distribué dans les JAR ou dans le `.mrpack` Sanctuary.
|
||||
|
||||
## Installation cliente facultative
|
||||
|
||||
1. Télécharger [Golden Days Base](https://www.curseforge.com/minecraft/texture-packs/golden-days)
|
||||
depuis sa page officielle.
|
||||
2. Télécharger [Golden Days Alpha](https://www.curseforge.com/minecraft/texture-packs/golden-days-alpha)
|
||||
depuis sa page officielle.
|
||||
3. Placer les deux ZIP sans les extraire dans le dossier `resourcepacks/` du
|
||||
client. Les noms doivent conserver les marqueurs `golden-days-base` et
|
||||
`golden-days-alpha` ; les espaces et `_` sont aussi reconnus.
|
||||
4. Laisser les deux packs désactivés dans l'écran vanilla. Ambiance les compose
|
||||
temporairement dans l'ordre **Base**, puis **Alpha**.
|
||||
|
||||
À l'entrée dans Alpha, Ambiance capture la pile sélectionnée exacte, ajoute les
|
||||
deux packs en mémoire et recharge les ressources. À la sortie ou à la
|
||||
déconnexion, la pile capturée est restaurée exactement. Le fichier d'options
|
||||
vanilla n'est jamais modifié : après une interruption ou un crash pendant un
|
||||
rechargement, le prochain démarrage retrouve donc la pile enregistrée.
|
||||
|
||||
Si un des deux packs manque ou si un rechargement échoue, le client reste
|
||||
jouable avec les textures vanilla et affiche un message lisible. Un serveur
|
||||
dédié n'a besoin d'aucun ZIP.
|
||||
|
||||
## Licence et redistribution
|
||||
|
||||
Golden Days est publié sous **All Rights Reserved**. Sa
|
||||
[licence officielle](https://poeticrainbow.github.io/golden-days/license/)
|
||||
interdit notamment de redistribuer ou de reconditionner les ressources sans
|
||||
autorisation. Sanctuary ne fournit que l'intégration locale ci-dessus et les
|
||||
liens officiels. Les archives de développement restent hors du dépôt et de
|
||||
tous les artefacts distribués.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Third-party notices
|
||||
|
||||
## Golden Days Base and Golden Days Alpha
|
||||
|
||||
Optional client resource packs by PoeticRainbow. No Golden Days asset is
|
||||
included in Ambiance or Sanctuary.
|
||||
|
||||
- Base project: https://www.curseforge.com/minecraft/texture-packs/golden-days
|
||||
- Alpha project: https://www.curseforge.com/minecraft/texture-packs/golden-days-alpha
|
||||
- License: https://poeticrainbow.github.io/golden-days/license/
|
||||
|
||||
Golden Days is All Rights Reserved. Players obtain the two archives separately
|
||||
from the official project pages for local use.
|
||||
+64
-4
@@ -42,6 +42,12 @@ dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("jar") {
|
||||
from("THIRD_PARTY_NOTICES.md") {
|
||||
rename { "THIRD_PARTY_NOTICES_ambiance.md" }
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("ambianceVisualApiSmoke", JavaExec) {
|
||||
group = "verification"
|
||||
description = "Checks bounded visual-effect requests exposed to gameplay modules."
|
||||
@@ -82,13 +88,21 @@ tasks.register("whiteDiscStreamSmoke", JavaExec) {
|
||||
mainClass = "fr.koka99cab.sanctuary26.ambiance.client.audio.LavaplayerAudioStreamSmoke"
|
||||
}
|
||||
|
||||
tasks.register("alphaTexturePackManagerSmoke", JavaExec) {
|
||||
group = "verification"
|
||||
description = "Checks local Golden Days detection, ordering and exact stack preservation."
|
||||
dependsOn tasks.named("testClasses")
|
||||
classpath = sourceSets.test.runtimeClasspath
|
||||
mainClass = "fr.koka99cab.sanctuary26.ambiance.client.AlphaTexturePackManagerSmoke"
|
||||
}
|
||||
|
||||
tasks.named("test") {
|
||||
failOnNoDiscoveredTests = false
|
||||
}
|
||||
|
||||
tasks.register("verifyAmbiance") {
|
||||
group = "verification"
|
||||
description = "Checks Ambiance alpha.19, including continuous white-disc PCM playback."
|
||||
description = "Checks Ambiance alpha.21, including corrected white-disc pitch and Alpha textures."
|
||||
inputs.files(fileTree("src/main/java"))
|
||||
inputs.files(fileTree("src/main/resources"))
|
||||
inputs.file(file("src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java"))
|
||||
@@ -147,7 +161,7 @@ tasks.register("verifyAmbiance") {
|
||||
def whiteDiscPlaybackSmoke = file(
|
||||
"src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java").text
|
||||
|
||||
if (project.version.toString() != "0.0.0-alpha.19"
|
||||
if (project.version.toString() != "0.0.0-alpha.21"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.125"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.126"
|
||||
|| migration.target?.modules?.ambiance != "0.0.0-alpha.1"
|
||||
@@ -357,11 +371,14 @@ tasks.register("verifyAmbiance") {
|
||||
|| !javaText.contains('initialWaitAttempted')
|
||||
|| !javaText.contains('CONTINUATION_FRAME_WAIT_MILLIS = 250L')
|
||||
|| !javaText.contains('player.provide(waitMillis, TimeUnit.MILLISECONDS)')
|
||||
|| !whiteDiscAudioPlayer.contains('channel.setPitch(1.0F)')
|
||||
|| !whiteDiscAudioPlayer.contains('PLAYBACK_PITCH = 4.0F / 3.0F')
|
||||
|| whiteDiscAudioPlayer.count('channel.setPitch(PLAYBACK_PITCH)') != 2
|
||||
|| !whiteDiscAudioPlayer.contains('handle.execute(channel -> channel.stop())')
|
||||
|| whiteDiscAudioPlayer.contains('.release()')
|
||||
|| !whiteDiscPlaybackSmoke.contains('https://www.youtube.com/watch?v=Ue5ZBe-GzSM')
|
||||
|| !whiteDiscPlaybackSmoke.contains('Decoded audible PCM data')
|
||||
|| !whiteDiscPlaybackSmoke.contains('PCM cadence: 100%% speed')
|
||||
|| !whiteDiscPlaybackSmoke.contains('stream.decodedTimelineMillis() != 4_000L')
|
||||
|| !whiteDiscPlaybackSmoke.contains('stream.paddedSilenceBytes() != 0L')
|
||||
|| !javaText.contains('SoundSource.RECORDS')
|
||||
|| !javaText.contains('channel.linearAttenuation(ATTENUATION_DISTANCE)')
|
||||
|| !javaText.contains('LONG_HOSTS = Set.of(')
|
||||
@@ -435,10 +452,53 @@ tasks.register("verifyAmbiance") {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("verifyAlphaTextures") {
|
||||
group = "verification"
|
||||
description = "Checks the alpha.21 local-only Golden Days overlay and exact restore contract."
|
||||
inputs.file(file("GOLDEN_DAYS.md"))
|
||||
inputs.file(file("THIRD_PARTY_NOTICES.md"))
|
||||
inputs.file(file("src/main/java/fr/koka99cab/sanctuary26/ambiance/client/AlphaTexturePackManager.java"))
|
||||
inputs.files(fileTree("src/main/resources/assets/ambiance/lang") { include "*.json" })
|
||||
inputs.file(rootProject.file("pack/migrations/26.2.0-alpha.218-alpha-indev-to-alpha.219.json"))
|
||||
doLast {
|
||||
def migration = new JsonSlurper().parse(rootProject.file(
|
||||
"pack/migrations/26.2.0-alpha.218-alpha-indev-to-alpha.219.json"))
|
||||
def manager = file(
|
||||
"src/main/java/fr/koka99cab/sanctuary26/ambiance/client/AlphaTexturePackManager.java").text
|
||||
def locales = ["fr_fr", "en_us", "ru_ru"].collect {
|
||||
new JsonSlurper().parse(file("src/main/resources/assets/ambiance/lang/${it}.json"))
|
||||
}
|
||||
def forbiddenArchives = rootProject.fileTree(rootProject.projectDir) {
|
||||
include "**/*golden*days*.zip", "**/*golden*days*.jar"
|
||||
exclude "**/build/**", "**/.gradle/**", "**/.git/**"
|
||||
}.files
|
||||
if (project.version.toString() != "0.0.0-alpha.21"
|
||||
|| migration.alpha_textures?.destination != "sanctuary:alpha"
|
||||
|| migration.alpha_textures?.client_only != true
|
||||
|| migration.alpha_textures?.bundled_assets != false
|
||||
|| migration.alpha_textures?.overlay_order != ["base", "alpha"]
|
||||
|| migration.alpha_textures?.previous_selection_restored_exactly != true
|
||||
|| migration.alpha_textures?.saved_options_modified != false
|
||||
|| migration.alpha_textures?.dedicated_server_files_required != false
|
||||
|| !manager.contains("SanctuaryDimensions.ALPHA")
|
||||
|| !manager.contains("previousSelection = List.copyOf")
|
||||
|| !manager.contains("selectionWithOverlay(previousSelection")
|
||||
|| manager.contains("updateResourcePacks")
|
||||
|| locales.any { !it.containsKey("message.ambiance.alpha_textures_missing")
|
||||
|| !it.containsKey("message.ambiance.alpha_textures_restore_failed") }
|
||||
|| !forbiddenArchives.isEmpty()
|
||||
|| !file("THIRD_PARTY_NOTICES.md").text.contains("No Golden Days asset")) {
|
||||
throw new GradleException("Ambiance alpha.21 Golden Days overlay contract is incomplete")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("check") {
|
||||
dependsOn tasks.named("verifyAmbiance")
|
||||
dependsOn tasks.named("ambianceScheduleSmoke")
|
||||
dependsOn tasks.named("ambianceVisualApiSmoke")
|
||||
dependsOn tasks.named("whiteDiscUrlSmoke")
|
||||
dependsOn tasks.named("whiteDiscStreamSmoke")
|
||||
dependsOn tasks.named("alphaTexturePackManagerSmoke")
|
||||
dependsOn tasks.named("verifyAlphaTextures")
|
||||
}
|
||||
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
package fr.koka99cab.sanctuary26.ambiance.client;
|
||||
|
||||
import fr.koka99cab.sanctuary26.ambiance.AmbianceMod;
|
||||
import fr.koka99cab.sanctuary26.sanctuary.world.SanctuaryDimensions;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.packs.repository.PackRepository;
|
||||
|
||||
/**
|
||||
* Applies locally installed Golden Days packs only while the player is in
|
||||
* {@code sanctuary:alpha}. The selected stack is changed in memory only; the
|
||||
* player's saved resource-pack options remain untouched.
|
||||
*/
|
||||
public final class AlphaTexturePackManager {
|
||||
static final String BASE_MARKER = "golden-days-base";
|
||||
static final String ALPHA_MARKER = "golden-days-alpha";
|
||||
private static final int MAX_RESTORE_RETRIES = 1;
|
||||
|
||||
private static boolean requestKnown;
|
||||
private static boolean alphaRequested;
|
||||
private static boolean reloadInProgress;
|
||||
private static boolean failedForCurrentRequest;
|
||||
private static boolean missingMessageShown;
|
||||
private static boolean reconcilePending = true;
|
||||
private static int restoreFailures;
|
||||
private static List<String> previousSelection = List.of();
|
||||
private static boolean previousSelectionCaptured;
|
||||
|
||||
private AlphaTexturePackManager() {
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
ClientTickEvents.END_CLIENT_TICK.register(AlphaTexturePackManager::tick);
|
||||
ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> request(client, false));
|
||||
}
|
||||
|
||||
private static void tick(Minecraft client) {
|
||||
boolean shouldUseAlphaTextures = client.level != null
|
||||
&& client.level.dimension().equals(SanctuaryDimensions.ALPHA);
|
||||
request(client, shouldUseAlphaTextures);
|
||||
if (!reloadInProgress && reconcilePending) {
|
||||
reconcilePending = false;
|
||||
reconcile(client);
|
||||
}
|
||||
}
|
||||
|
||||
private static void request(Minecraft client, boolean requested) {
|
||||
if (requestKnown && requested == alphaRequested) return;
|
||||
alphaRequested = requested;
|
||||
requestKnown = true;
|
||||
failedForCurrentRequest = false;
|
||||
missingMessageShown = false;
|
||||
restoreFailures = 0;
|
||||
if (requested && !previousSelectionCaptured) {
|
||||
PackRepository repository = client.getResourcePackRepository();
|
||||
repository.reload();
|
||||
previousSelection = List.copyOf(repository.getSelectedIds());
|
||||
previousSelectionCaptured = true;
|
||||
}
|
||||
reconcilePending = true;
|
||||
}
|
||||
|
||||
private static void reconcile(Minecraft client) {
|
||||
PackRepository repository = client.getResourcePackRepository();
|
||||
repository.reload();
|
||||
List<String> selected = List.copyOf(repository.getSelectedIds());
|
||||
|
||||
if (alphaRequested && !failedForCurrentRequest) {
|
||||
Optional<PackPair> packs = findPacks(repository.getAvailableIds());
|
||||
if (packs.isEmpty()) {
|
||||
failedForCurrentRequest = true;
|
||||
showMissingPackMessage(client);
|
||||
applyIfDifferent(client, selected, previousSelection, false);
|
||||
return;
|
||||
}
|
||||
List<String> desired = selectionWithOverlay(previousSelection, packs.orElseThrow());
|
||||
applyIfDifferent(client, selected, desired, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!previousSelectionCaptured) return;
|
||||
applyIfDifferent(client, selected, previousSelection, false);
|
||||
}
|
||||
|
||||
private static void applyIfDifferent(Minecraft client, List<String> selected,
|
||||
List<String> desired, boolean enablingAlpha) {
|
||||
if (selected.equals(desired)) {
|
||||
if (!enablingAlpha && !alphaRequested) clearSnapshot();
|
||||
return;
|
||||
}
|
||||
client.getResourcePackRepository().setSelected(desired);
|
||||
reloadInProgress = true;
|
||||
AmbianceMod.LOGGER.info("[{}] Reloading client resources for Alpha texture mode: {}.",
|
||||
AmbianceMod.DISPLAY_NAME, enablingAlpha ? "enabled" : "disabled");
|
||||
client.reloadResourcePacks().whenComplete((ignored, error) -> client.execute(() -> {
|
||||
reloadInProgress = false;
|
||||
if (error != null) {
|
||||
AmbianceMod.LOGGER.error("[{}] Could not {} the Golden Days Alpha overlay.",
|
||||
AmbianceMod.DISPLAY_NAME, enablingAlpha ? "enable" : "restore", error);
|
||||
if (enablingAlpha) {
|
||||
failedForCurrentRequest = true;
|
||||
reconcilePending = true;
|
||||
} else if (++restoreFailures <= MAX_RESTORE_RETRIES) {
|
||||
reconcilePending = true;
|
||||
} else {
|
||||
client.getResourcePackRepository().setSelected(previousSelection);
|
||||
showRestoreFailureMessage(client);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!enablingAlpha && !alphaRequested) clearSnapshot();
|
||||
if (enablingAlpha != alphaRequested) reconcilePending = true;
|
||||
}));
|
||||
}
|
||||
|
||||
static Optional<PackPair> findPacks(Collection<String> availableIds) {
|
||||
Optional<String> base = findPack(availableIds, BASE_MARKER);
|
||||
Optional<String> alpha = findPack(availableIds, ALPHA_MARKER);
|
||||
return base.isPresent() && alpha.isPresent()
|
||||
? Optional.of(new PackPair(base.orElseThrow(), alpha.orElseThrow()))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
static List<String> selectionWithOverlay(Collection<String> previous, PackPair packs) {
|
||||
List<String> desired = selectedWithoutGoldenDays(previous);
|
||||
// Pack order is bottom-to-top: Base first, then its Alpha overlay.
|
||||
desired.add(packs.base());
|
||||
desired.add(packs.alpha());
|
||||
return List.copyOf(desired);
|
||||
}
|
||||
|
||||
private static List<String> selectedWithoutGoldenDays(Collection<String> selectedIds) {
|
||||
List<String> result = new ArrayList<>(selectedIds.size());
|
||||
for (String id : selectedIds) {
|
||||
if (!isGoldenDaysPack(id)) result.add(id);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Optional<String> findPack(Collection<String> availableIds, String marker) {
|
||||
return availableIds.stream()
|
||||
.filter(id -> normalized(id).contains(marker))
|
||||
.sorted(Comparator.naturalOrder())
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
static boolean isGoldenDaysPack(String id) {
|
||||
String normalized = normalized(id);
|
||||
return normalized.contains(BASE_MARKER) || normalized.contains(ALPHA_MARKER);
|
||||
}
|
||||
|
||||
private static String normalized(String id) {
|
||||
return id.toLowerCase(Locale.ROOT).replace('_', '-').replace(' ', '-');
|
||||
}
|
||||
|
||||
private static void clearSnapshot() {
|
||||
previousSelection = List.of();
|
||||
previousSelectionCaptured = false;
|
||||
restoreFailures = 0;
|
||||
}
|
||||
|
||||
private static void showMissingPackMessage(Minecraft client) {
|
||||
if (!missingMessageShown && client.player != null) {
|
||||
client.gui.hud.getChat().addClientSystemMessage(
|
||||
Component.translatable("message.ambiance.alpha_textures_missing"));
|
||||
missingMessageShown = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void showRestoreFailureMessage(Minecraft client) {
|
||||
if (client.player != null) {
|
||||
client.gui.hud.getChat().addClientSystemMessage(
|
||||
Component.translatable("message.ambiance.alpha_textures_restore_failed"));
|
||||
}
|
||||
}
|
||||
|
||||
record PackPair(String base, String alpha) {
|
||||
PackPair {
|
||||
if (base == null || alpha == null || base.equals(alpha)) {
|
||||
throw new IllegalArgumentException("Golden Days Base and Alpha packs must be distinct");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ public final class AmbianceClient implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
RealtimeClient.initialize();
|
||||
AlphaTexturePackManager.register();
|
||||
CelestialSkyRenderer.register();
|
||||
ClientTickEvents.END_CLIENT_TICK.register(DynamicTorchLights::tick);
|
||||
ClientPlayNetworking.registerGlobalReceiver(AmbianceEnvironmentPayload.TYPE, (payload, context) ->
|
||||
|
||||
+26
-1
@@ -19,6 +19,11 @@ final class LavaplayerAudioStream implements AudioStream {
|
||||
private final AudioPlayer player;
|
||||
private byte[] pending = new byte[0];
|
||||
private int pendingOffset;
|
||||
private long decodedBytes;
|
||||
private long paddedSilenceBytes;
|
||||
private long firstFrameTimecode = -1L;
|
||||
private long lastFrameTimecode = -1L;
|
||||
private int decodedFrames;
|
||||
private boolean initialWaitAttempted;
|
||||
private volatile boolean closed;
|
||||
private volatile boolean ended;
|
||||
@@ -41,18 +46,25 @@ final class LavaplayerAudioStream implements AudioStream {
|
||||
int length = Math.min(output.remaining(), pending.length - pendingOffset);
|
||||
output.put(pending, pendingOffset, length);
|
||||
pendingOffset += length;
|
||||
decodedBytes += length;
|
||||
continue;
|
||||
}
|
||||
AudioFrame frame = nextFrame();
|
||||
if (frame == null) {
|
||||
if (ended) break;
|
||||
while (output.hasRemaining()) output.put((byte) 0);
|
||||
while (output.hasRemaining()) {
|
||||
output.put((byte) 0);
|
||||
paddedSilenceBytes++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (frame.isTerminator()) {
|
||||
ended = true;
|
||||
break;
|
||||
}
|
||||
if (firstFrameTimecode < 0L) firstFrameTimecode = frame.getTimecode();
|
||||
lastFrameTimecode = frame.getTimecode();
|
||||
decodedFrames++;
|
||||
pending = frame.getData();
|
||||
pendingOffset = 0;
|
||||
}
|
||||
@@ -86,6 +98,19 @@ final class LavaplayerAudioStream implements AudioStream {
|
||||
return player == expectedPlayer;
|
||||
}
|
||||
|
||||
long decodedBytes() {
|
||||
return decodedBytes;
|
||||
}
|
||||
|
||||
long paddedSilenceBytes() {
|
||||
return paddedSilenceBytes;
|
||||
}
|
||||
|
||||
long decodedTimelineMillis() {
|
||||
if (decodedFrames == 0) return 0L;
|
||||
return lastFrameTimecode - firstFrameTimecode + 20L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (closed) return;
|
||||
|
||||
+7
-2
@@ -36,6 +36,8 @@ public final class WhiteDiscAudioPlayer {
|
||||
private static final long MAXIMUM_TRACK_MILLIS = 30L * 60L * 1_000L;
|
||||
private static final long FINISHED_GRACE_NANOS = 5_000_000_000L;
|
||||
private static final float ATTENUATION_DISTANCE = 64.0F;
|
||||
/** Compensates Lavaplayer's low AAC cadence before PCM reaches OpenAL. */
|
||||
static final float PLAYBACK_PITCH = 4.0F / 3.0F;
|
||||
private static final DefaultAudioPlayerManager MANAGER = createManager();
|
||||
private static final Map<Long, PendingStart> PENDING_STARTS = new HashMap<>();
|
||||
private static final Map<Long, Long> REQUESTS = new HashMap<>();
|
||||
@@ -150,7 +152,7 @@ public final class WhiteDiscAudioPlayer {
|
||||
try {
|
||||
channel.setSelfPosition(Vec3.atCenterOf(pos));
|
||||
channel.setRelative(false);
|
||||
channel.setPitch(1.0F);
|
||||
channel.setPitch(PLAYBACK_PITCH);
|
||||
channel.linearAttenuation(ATTENUATION_DISTANCE);
|
||||
channel.setVolume(volume);
|
||||
channel.attachBufferStream(stream);
|
||||
@@ -212,7 +214,10 @@ public final class WhiteDiscAudioPlayer {
|
||||
continue;
|
||||
}
|
||||
float volume = client.options.getFinalSoundSourceVolume(SoundSource.RECORDS);
|
||||
playback.handle().execute(channel -> channel.setVolume(volume));
|
||||
playback.handle().execute(channel -> {
|
||||
channel.setPitch(PLAYBACK_PITCH);
|
||||
channel.setVolume(volume);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,5 +32,7 @@
|
||||
"message.ambiance.white_disc.loading": "Loading YouTube video…",
|
||||
"message.ambiance.white_disc.playing": "Now playing: %s",
|
||||
"message.ambiance.white_disc.failed": "This YouTube video could not be played.",
|
||||
"message.ambiance.white_disc.too_long": "This video is live or longer than 30 minutes."
|
||||
"message.ambiance.white_disc.too_long": "This video is live or longer than 30 minutes.",
|
||||
"message.ambiance.alpha_textures_missing": "Alpha textures are unavailable: install Golden Days Base then Golden Days Alpha in resourcepacks and leave them disabled.",
|
||||
"message.ambiance.alpha_textures_restore_failed": "The previous resource-pack stack could not be reloaded. It will be restored on the next start."
|
||||
}
|
||||
|
||||
@@ -32,5 +32,7 @@
|
||||
"message.ambiance.white_disc.loading": "Chargement de la vidéo YouTube…",
|
||||
"message.ambiance.white_disc.playing": "Lecture : %s",
|
||||
"message.ambiance.white_disc.failed": "Impossible de lire cette vidéo YouTube.",
|
||||
"message.ambiance.white_disc.too_long": "Cette vidéo est en direct ou dépasse 30 minutes."
|
||||
"message.ambiance.white_disc.too_long": "Cette vidéo est en direct ou dépasse 30 minutes.",
|
||||
"message.ambiance.alpha_textures_missing": "Textures Alpha indisponibles : installez Golden Days Base puis Golden Days Alpha dans resourcepacks en les laissant désactivés.",
|
||||
"message.ambiance.alpha_textures_restore_failed": "La pile de packs précédente n’a pas pu être rechargée. Elle sera restaurée au prochain démarrage."
|
||||
}
|
||||
|
||||
@@ -32,5 +32,7 @@
|
||||
"message.ambiance.white_disc.loading": "Загрузка видео YouTube…",
|
||||
"message.ambiance.white_disc.playing": "Сейчас играет: %s",
|
||||
"message.ambiance.white_disc.failed": "Не удалось воспроизвести это видео YouTube.",
|
||||
"message.ambiance.white_disc.too_long": "Это прямая трансляция или видео длиннее 30 минут."
|
||||
"message.ambiance.white_disc.too_long": "Это прямая трансляция или видео длиннее 30 минут.",
|
||||
"message.ambiance.alpha_textures_missing": "Текстуры Alpha недоступны: установите Golden Days Base, затем Golden Days Alpha в resourcepacks и оставьте их выключенными.",
|
||||
"message.ambiance.alpha_textures_restore_failed": "Не удалось перезагрузить прежний набор ресурсов. Он будет восстановлен при следующем запуске."
|
||||
}
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package fr.koka99cab.sanctuary26.ambiance.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Executable tests for local Golden Days discovery and exact stack composition. */
|
||||
public final class AlphaTexturePackManagerSmoke {
|
||||
private AlphaTexturePackManagerSmoke() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
var packs = AlphaTexturePackManager.findPacks(List.of(
|
||||
"vanilla",
|
||||
"file/Golden Days Base 16.2 [1.20 to 26.2].zip",
|
||||
"file/golden_days_alpha_16.2.zip"
|
||||
)).orElseThrow(() -> new AssertionError("Golden Days packs were not detected"));
|
||||
|
||||
List<String> previous = List.of(
|
||||
"vanilla", "file/custom.zip", "file/golden-days-alpha-old.zip");
|
||||
List<String> desired = AlphaTexturePackManager.selectionWithOverlay(previous, packs);
|
||||
require(desired.equals(List.of("vanilla", "file/custom.zip", packs.base(), packs.alpha())),
|
||||
"Base and Alpha must be appended in bottom-to-top order without disturbing custom packs");
|
||||
require(previous.equals(List.of(
|
||||
"vanilla", "file/custom.zip", "file/golden-days-alpha-old.zip")),
|
||||
"Composing the overlay must not mutate the captured stack");
|
||||
require(AlphaTexturePackManager.findPacks(List.of("file/golden-days-base.zip")).isEmpty(),
|
||||
"A partial installation must keep the vanilla stack");
|
||||
require(AlphaTexturePackManager.isGoldenDaysPack("FILE/GOLDEN_DAYS_ALPHA.ZIP"),
|
||||
"Pack matching must be case- and separator-insensitive");
|
||||
require(!AlphaTexturePackManager.isGoldenDaysPack("file/custom-alpha.zip"),
|
||||
"Unrelated packs must never be removed from the captured stack");
|
||||
}
|
||||
|
||||
private static void require(boolean condition, String message) {
|
||||
if (!condition) throw new AssertionError(message);
|
||||
}
|
||||
}
|
||||
+3
@@ -22,6 +22,9 @@ public final class LavaplayerAudioStreamSmoke {
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (Math.abs(WhiteDiscAudioPlayer.PLAYBACK_PITCH - 4.0F / 3.0F) > 0.0001F) {
|
||||
throw new IllegalStateException("The white-disc AAC pitch compensation changed");
|
||||
}
|
||||
Queue<AudioFrame> frames = new ArrayDeque<>();
|
||||
Pcm16AudioDataFormat format = new Pcm16AudioDataFormat(
|
||||
1, LavaplayerAudioStream.SAMPLE_RATE, FRAME_SAMPLES, false);
|
||||
|
||||
+30
-14
@@ -30,29 +30,45 @@ public final class WhiteDiscPlaybackSmoke {
|
||||
AudioPlayer player = manager.createPlayer();
|
||||
player.playTrack(track);
|
||||
LavaplayerAudioStream stream = new LavaplayerAudioStream(player);
|
||||
int decodedBytes = 0;
|
||||
int totalBytes = 0;
|
||||
long squaredSampleSum = 0L;
|
||||
int sampleCount = 0;
|
||||
int peakSample = 0;
|
||||
for (int index = 0; index < 4; index++) {
|
||||
ByteBuffer pcm = stream.read(LavaplayerAudioStream.SAMPLE_RATE * 2);
|
||||
if (pcm == null) break;
|
||||
while (pcm.hasRemaining()) {
|
||||
totalBytes++;
|
||||
if (pcm.get() != 0) decodedBytes++;
|
||||
totalBytes += pcm.remaining();
|
||||
while (pcm.remaining() >= 2) {
|
||||
int low = Byte.toUnsignedInt(pcm.get());
|
||||
int high = pcm.get();
|
||||
short sample = (short) ((high << 8) | low);
|
||||
int magnitude = Math.abs((int) sample);
|
||||
peakSample = Math.max(peakSample, magnitude);
|
||||
squaredSampleSum += (long) sample * sample;
|
||||
sampleCount++;
|
||||
}
|
||||
}
|
||||
if (decodedBytes == 0) {
|
||||
throw new IllegalStateException("YouTube playback produced no audible PCM data");
|
||||
}
|
||||
double audibleRatio = (double) decodedBytes / totalBytes;
|
||||
if (totalBytes != LavaplayerAudioStream.SAMPLE_RATE * 2 * 4) {
|
||||
int expectedBytes = LavaplayerAudioStream.SAMPLE_RATE * 2 * 4;
|
||||
if (totalBytes != expectedBytes) {
|
||||
throw new IllegalStateException("YouTube playback did not fill four PCM seconds");
|
||||
}
|
||||
if (audibleRatio < 0.75) {
|
||||
throw new IllegalStateException("YouTube PCM stream was mostly silence: "
|
||||
+ Math.round(audibleRatio * 100.0) + "% audible bytes");
|
||||
if (stream.decodedBytes() != expectedBytes || stream.paddedSilenceBytes() != 0L) {
|
||||
throw new IllegalStateException("YouTube playback was not 100% decoded PCM: "
|
||||
+ stream.decodedBytes() + " decoded bytes and "
|
||||
+ stream.paddedSilenceBytes() + " padded bytes");
|
||||
}
|
||||
System.out.printf("Decoded audible PCM data: %.1f%% at %.0f Hz from %s%n",
|
||||
audibleRatio * 100.0, stream.getFormat().getSampleRate(), track.getInfo().title);
|
||||
if (stream.decodedTimelineMillis() != 4_000L) {
|
||||
throw new IllegalStateException("PCM cadence mismatch: four seconds of samples cover "
|
||||
+ stream.decodedTimelineMillis() + " ms of the YouTube timeline");
|
||||
}
|
||||
double rmsSample = Math.sqrt((double) squaredSampleSum / sampleCount);
|
||||
if (rmsSample < 256.0 || peakSample < 2_048) {
|
||||
throw new IllegalStateException("YouTube PCM signal is too quiet: RMS "
|
||||
+ Math.round(rmsSample) + ", peak " + peakSample);
|
||||
}
|
||||
System.out.printf(
|
||||
"PCM cadence: 100%% speed, 4000 ms decoded into 4000 ms at %.0f Hz; RMS %.0f, peak %d from %s%n",
|
||||
stream.getFormat().getSampleRate(), rmsSample, peakSample, track.getInfo().title);
|
||||
stream.close();
|
||||
} finally {
|
||||
manager.shutdown();
|
||||
|
||||
+332
-156
@@ -3437,8 +3437,8 @@ tasks.register("verifyProgressivePauseMenuRelease") {
|
||||
[(locale): new JsonSlurper().parse(file(
|
||||
"sanctuary/src/main/resources/assets/sanctuary/lang/${locale}.json"))]
|
||||
}
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.121"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.122"
|
||||
|| rootProject.onlyfun_version != "0.0.0-alpha.25"
|
||||
|| release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version
|
||||
|| migration.source?.modules != [sanctuary: "0.0.0-alpha.108", onlyfun: "0.0.0-alpha.17"]
|
||||
@@ -3487,7 +3487,7 @@ tasks.register("verifyMirrorLavenderDrawerRelease") {
|
||||
def redStonerRegistry = file(
|
||||
"redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/registry/RedStonerRegistries.java").text
|
||||
def drawerRecipe = file("redstoner/src/main/resources/data/redstoner/recipe/drawer.json")
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.anotherworld_version != "0.0.0-alpha.55"
|
||||
|| rootProject.redstoner_version != "0.0.0-alpha.11"
|
||||
|| release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version
|
||||
@@ -3993,7 +3993,7 @@ project(":redstoner") {
|
||||
inputs.file(rootProject.file("pack/migrations/26.2.0-alpha.167-cobble-dungeon-ownership-to-alpha.168.json"))
|
||||
inputs.file(rootProject.file("pack/migrations/26.2.0-alpha.185-computer-recipes-to-alpha.186.json"))
|
||||
inputs.file(rootProject.file("pack/migrations/26.2.0-alpha.191-mirror-lavender-drawer-to-alpha.192.json"))
|
||||
inputs.file(rootProject.file("pack/migrations/26.2.0-alpha.216-storage-terminal-to-alpha.217.json"))
|
||||
inputs.file(rootProject.file("pack/migrations/26.2.0-alpha.217-storage-terminal-to-alpha.218.json"))
|
||||
doLast {
|
||||
def registry = file("src/main/java/fr/koka99cab/sanctuary26/redstoner/registry/RedStonerRegistries.java").text
|
||||
def javaText = fileTree("src/main/java").matching { include "**/*.java" }.files*.text.join("\n")
|
||||
@@ -4013,7 +4013,7 @@ project(":redstoner") {
|
||||
def drawerMigration = new JsonSlurper().parse(rootProject.file(
|
||||
"pack/migrations/26.2.0-alpha.191-mirror-lavender-drawer-to-alpha.192.json"))
|
||||
def terminalMigration = new JsonSlurper().parse(rootProject.file(
|
||||
"pack/migrations/26.2.0-alpha.216-storage-terminal-to-alpha.217.json"))
|
||||
"pack/migrations/26.2.0-alpha.217-storage-terminal-to-alpha.218.json"))
|
||||
def requiredIds = [
|
||||
"eight_bit_computer", "controller", "personal_computer", "drawer", "particuleur", "storage_terminal"]
|
||||
def missingIds = requiredIds.findAll { !registry.contains("id(\"${it}\")") }
|
||||
@@ -4101,10 +4101,10 @@ project(":redstoner") {
|
||||
if (project.version.toString() != "0.0.0-alpha.11"
|
||||
|| manifest.custom?.sanctuary26?.data_version != 3
|
||||
|| manifest.custom?.sanctuary26?.network_protocol != 6
|
||||
|| terminalMigration.source?.pack_version != "26.2.0-alpha.216"
|
||||
|| terminalMigration.source?.pack_version != "26.2.0-alpha.217"
|
||||
|| terminalMigration.source?.modules != [
|
||||
redstoner: "0.0.0-alpha.10", onlyfun: "0.0.0-alpha.24", sanctuary: "0.0.0-alpha.120"]
|
||||
|| terminalMigration.target?.pack_version != "26.2.0-alpha.217"
|
||||
|| terminalMigration.target?.pack_version != "26.2.0-alpha.218"
|
||||
|| terminalMigration.target?.modules != [
|
||||
redstoner: "0.0.0-alpha.11", onlyfun: "0.0.0-alpha.25", sanctuary: "0.0.0-alpha.121"]
|
||||
|| terminalMigration.storage_terminal?.owner != "redstoner"
|
||||
@@ -4259,9 +4259,9 @@ tasks.register("verifyShopPricingLayoutRelease") {
|
||||
"pack/migrations/26.2.0-alpha.192-shop-pricing-layout-to-alpha.193.json"))
|
||||
def release = new JsonSlurper().parse(file("pack/release.json"))
|
||||
def index = new JsonSlurper().parse(file("pack/prism/modrinth.index.json"))
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.onlyfun_version != "0.0.0-alpha.25"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.121"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.122"
|
||||
|| release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.192"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.193"
|
||||
@@ -4304,7 +4304,7 @@ tasks.register("verifyCuisineCropsRelease") {
|
||||
def climate = file("itsalive/src/main/java/fr/koka99cab/sanctuary26/itsalive/agriculture/ClimateCropForaging.java").text
|
||||
def rice = file("itsalive/src/main/java/fr/koka99cab/sanctuary26/itsalive/agriculture/RiceCropBlock.java").text
|
||||
def bean = file("itsalive/src/main/java/fr/koka99cab/sanctuary26/itsalive/agriculture/BeanCropBlock.java").text
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.36"
|
||||
|| release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.193"
|
||||
@@ -4353,9 +4353,9 @@ tasks.register("verifyShopCsvBossGatesRelease") {
|
||||
def bossGate = file("onlyfun/src/main/java/fr/koka99cab/sanctuary26/onlyfun/shop/OnlyFunBossShopGate.java").text
|
||||
def catalog = file("onlyfun/src/main/java/fr/koka99cab/sanctuary26/onlyfun/shop/OnlyFunShopCatalog.java").text
|
||||
def offerCatalog = file("sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopOfferCatalog.java").text
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.onlyfun_version != "0.0.0-alpha.25"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.121"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.122"
|
||||
|| release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.194"
|
||||
|| migration.source?.modules != [onlyfun: "0.0.0-alpha.18", sanctuary: "0.0.0-alpha.110"]
|
||||
@@ -4399,7 +4399,7 @@ tasks.register("verifyCulinaryMailboxGrappleFixesRelease") {
|
||||
def release = new JsonSlurper().parse(file("pack/release.json"))
|
||||
def prism = new JsonSlurper().parse(file("pack/prism/modrinth.index.json"))
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.195"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.196"
|
||||
|| migration.target?.modules != [
|
||||
@@ -4417,10 +4417,10 @@ tasks.register("verifyCulinaryMailboxGrappleFixesRelease") {
|
||||
|| migration.distribution?.jei?.target != "30.26.0.182"
|
||||
|| migration.compatibility?.save_migration_required != false
|
||||
|| migration.compatibility?.registry_ids_changed != false
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')) {
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')) {
|
||||
throw new GradleException("The alpha.196 culinary, mailbox and grapple release contract is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -4445,9 +4445,9 @@ tasks.register("verifyQuestRequestsCauldronBatchesRelease") {
|
||||
def prism = new JsonSlurper().parse(file("pack/prism/modrinth.index.json"))
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def sanctuaryManifest = new JsonSlurper().parse(file("sanctuary/src/main/resources/fabric.mod.json"))
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.36"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.121"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.122"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.196"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.197"
|
||||
|| migration.target?.modules != [itsalive: "0.0.0-alpha.29", sanctuary: "0.0.0-alpha.113"]
|
||||
@@ -4465,10 +4465,10 @@ tasks.register("verifyQuestRequestsCauldronBatchesRelease") {
|
||||
|| migration.distribution?.jei?.target != "30.26.0.186"
|
||||
|| migration.compatibility?.sanctuary_target_network_protocol != 19
|
||||
|| sanctuaryManifest.custom?.sanctuary26?.network_protocol != 22
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')) {
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')) {
|
||||
throw new GradleException("The alpha.197 quest-request and cauldron-batch release contract is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -4495,7 +4495,7 @@ tasks.register("verifyFermentationBarrelAutomationRelease") {
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def packwizIndex = file("pack/packwiz/index.toml").text
|
||||
def itsAliveManifest = new JsonSlurper().parse(file("itsalive/src/main/resources/fabric.mod.json"))
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.36"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.197"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.198"
|
||||
@@ -4514,10 +4514,10 @@ tasks.register("verifyFermentationBarrelAutomationRelease") {
|
||||
|| migration.distribution?.packwiz_index_refreshed != true
|
||||
|| itsAliveManifest.custom?.sanctuary26?.data_version != 3
|
||||
|| itsAliveManifest.custom?.sanctuary26?.network_protocol != 4
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.36.jar"')) {
|
||||
throw new GradleException("The alpha.198 fermentation barrel release contract is incomplete")
|
||||
}
|
||||
@@ -4545,9 +4545,9 @@ tasks.register("verifyQuestRequestContractsRelease") {
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def packwizIndex = file("pack/packwiz/index.toml").text
|
||||
def sanctuaryManifest = new JsonSlurper().parse(file("sanctuary/src/main/resources/fabric.mod.json"))
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.36"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.121"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.122"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.198"
|
||||
|| migration.source?.modules?.sanctuary != "0.0.0-alpha.114"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.199"
|
||||
@@ -4559,12 +4559,12 @@ tasks.register("verifyQuestRequestContractsRelease") {
|
||||
|| migration.quest_request_contracts?.chat_accept_revalidates_distance_owner_sign_and_claim != true
|
||||
|| migration.compatibility?.sanctuary_target_network_protocol != 20
|
||||
|| sanctuaryManifest.custom?.sanctuary26?.network_protocol != 22
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.36.jar"')
|
||||
|| !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.121.jar"')) {
|
||||
|| !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.122.jar"')) {
|
||||
throw new GradleException("The alpha.199 quest-request contract release is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -4600,8 +4600,8 @@ tasks.register("verifyWeatherTntAmbianceRelease") {
|
||||
def ambianceManifest = new JsonSlurper().parse(file("ambiance/src/main/resources/fabric.mod.json"))
|
||||
def ouchManifest = new JsonSlurper().parse(file("ouch/src/main/resources/fabric.mod.json"))
|
||||
def rootBuild = file("build.gradle").text
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.19"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.21"
|
||||
|| rootProject.ouch_version != "0.0.0-alpha.10"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.199"
|
||||
|| migration.source?.modules != [ambiance: "0.0.0-alpha.11", ouch: "0.0.0-alpha.8"]
|
||||
@@ -4634,11 +4634,11 @@ tasks.register("verifyWeatherTntAmbianceRelease") {
|
||||
|| !weatherTnt.contains("AmbianceDailyWeather.CLEAR")
|
||||
|| !weatherTnt.contains("CLEAR_WEATHER_TICKS = 864_000")
|
||||
|| weatherTnt.contains("setWeatherParameters")
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.19.jar"')
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"')
|
||||
|| !packwizIndex.contains('file = "mods/ouch-0.0.0-alpha.10.jar"')) {
|
||||
throw new GradleException("The alpha.200 Weather TNT and Ambiance release is incomplete")
|
||||
}
|
||||
@@ -4666,8 +4666,8 @@ tasks.register("verifyQuestRequestEscrowRelease") {
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def packwizIndex = file("pack/packwiz/index.toml").text
|
||||
def sanctuaryManifest = new JsonSlurper().parse(file("sanctuary/src/main/resources/fabric.mod.json"))
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.121"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.122"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.200"
|
||||
|| migration.source?.modules?.sanctuary != "0.0.0-alpha.115"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.201"
|
||||
@@ -4681,11 +4681,11 @@ tasks.register("verifyQuestRequestEscrowRelease") {
|
||||
|| migration.compatibility?.sanctuary_target_network_protocol != 21
|
||||
|| sanctuaryManifest.custom?.sanctuary26?.data_version != 11
|
||||
|| sanctuaryManifest.custom?.sanctuary26?.network_protocol != 22
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.121.jar"')) {
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.122.jar"')) {
|
||||
throw new GradleException("The alpha.201 quest-request escrow release is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -4720,11 +4720,11 @@ tasks.register("verifyWaystoneShopCulinaryAlpha202Release") {
|
||||
"iliketomoveit/src/main/resources/fabric.mod.json"))
|
||||
def sanctuaryManifest = new JsonSlurper().parse(file(
|
||||
"sanctuary/src/main/resources/fabric.mod.json"))
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.anotherworld_version != "0.0.0-alpha.55"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.36"
|
||||
|| rootProject.iliketomoveit_version != "0.0.0-alpha.15"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.121"
|
||||
|| rootProject.iliketomoveit_version != "0.0.0-alpha.16"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.122"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.201"
|
||||
|| migration.source?.modules != [
|
||||
itsalive: "0.0.0-alpha.30",
|
||||
@@ -4760,14 +4760,14 @@ tasks.register("verifyWaystoneShopCulinaryAlpha202Release") {
|
||||
|| moveItManifest.custom?.sanctuary26?.network_protocol != 5
|
||||
|| sanctuaryManifest.custom?.sanctuary26?.data_version != 11
|
||||
|| sanctuaryManifest.custom?.sanctuary26?.network_protocol != 22
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.55.jar"')
|
||||
|| !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.36.jar"')
|
||||
|| !packwizIndex.contains('file = "mods/iliketomoveit-0.0.0-alpha.15.jar"')
|
||||
|| !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.121.jar"')) {
|
||||
|| !packwizIndex.contains('file = "mods/iliketomoveit-0.0.0-alpha.16.jar"')
|
||||
|| !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.122.jar"')) {
|
||||
throw new GradleException("The alpha.202 Waystone, Shop and culinary lectern release is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -4880,9 +4880,9 @@ tasks.register("verifySafeVaultFeature") {
|
||||
def image = javax.imageio.ImageIO.read(file("anotherworld/src/main/resources/assets/anotherworld/textures/${path}"))
|
||||
image == null || image.width != size[0] || image.height != size[1]
|
||||
}.keySet()
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.anotherworld_version != "0.0.0-alpha.55"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.121"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.122"
|
||||
|| migration.schema_version != 1
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.201"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.202"
|
||||
@@ -5072,7 +5072,7 @@ tasks.register("verifySafeVaultInterfaceAlpha203Release") {
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def packwizIndex = file("pack/packwiz/index.toml").text
|
||||
def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.28.0.193.jar" }
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.anotherworld_version != "0.0.0-alpha.55"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.202"
|
||||
|| migration.source?.modules != [anotherworld: "0.0.0-alpha.50"]
|
||||
@@ -5090,9 +5090,9 @@ tasks.register("verifySafeVaultInterfaceAlpha203Release") {
|
||||
|| migration.distribution?.jei?.modrinth_version_id != "XXTFqqwG"
|
||||
|| migration.distribution?.jei?.prism_manifest_updated != true
|
||||
|| release.pack_version != rootProject.pack_version
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != rootProject.pack_version
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.55.jar"')
|
||||
|| packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.50.jar"')
|
||||
|| jeiFiles.size() != 1
|
||||
@@ -5118,7 +5118,7 @@ tasks.register("verifySafeVaultFixAlpha204Release") {
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def packwizIndex = file("pack/packwiz/index.toml").text
|
||||
def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.28.0.193.jar" }
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.anotherworld_version != "0.0.0-alpha.55"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.203"
|
||||
|| migration.source?.modules != [anotherworld: "0.0.0-alpha.51"]
|
||||
@@ -5144,9 +5144,9 @@ tasks.register("verifySafeVaultFixAlpha204Release") {
|
||||
|| migration.distribution?.jei?.modrinth_version_id != "OcMayhUH"
|
||||
|| migration.distribution?.jei?.prism_manifest_updated != true
|
||||
|| release.pack_version != rootProject.pack_version
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != rootProject.pack_version
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.55.jar"')
|
||||
|| packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.51.jar"')
|
||||
|| jeiFiles.size() != 1
|
||||
@@ -5172,7 +5172,7 @@ tasks.register("verifySafeVaultCubeAlpha205Release") {
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def packwizIndex = file("pack/packwiz/index.toml").text
|
||||
def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.28.0.193.jar" }
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.anotherworld_version != "0.0.0-alpha.55"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.204"
|
||||
|| migration.source?.modules != [anotherworld: "0.0.0-alpha.52"]
|
||||
@@ -5201,9 +5201,9 @@ tasks.register("verifySafeVaultCubeAlpha205Release") {
|
||||
|| migration.distribution?.jei?.modrinth_version_id != "NtfJDMhk"
|
||||
|| migration.distribution?.jei?.prism_manifest_updated != true
|
||||
|| release.pack_version != rootProject.pack_version
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != rootProject.pack_version
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.55.jar"')
|
||||
|| packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.52.jar"')
|
||||
|| jeiFiles.size() != 1
|
||||
@@ -5230,7 +5230,7 @@ tasks.register("verifySafeVaultCtmAlpha206Release") {
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def packwizIndex = file("pack/packwiz/index.toml").text
|
||||
def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.28.0.193.jar" }
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.anotherworld_version != "0.0.0-alpha.55"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.205"
|
||||
|| migration.source?.modules != [anotherworld: "0.0.0-alpha.53"]
|
||||
@@ -5253,9 +5253,9 @@ tasks.register("verifySafeVaultCtmAlpha206Release") {
|
||||
|| migration.compatibility?.pack_release_updated != true
|
||||
|| migration.distribution?.packwiz_index_refreshed != true
|
||||
|| release.pack_version != rootProject.pack_version
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != rootProject.pack_version
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.55.jar"')
|
||||
|| packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.53.jar"')
|
||||
|| jeiFiles.size() != 1
|
||||
@@ -5282,7 +5282,7 @@ tasks.register("verifySafeVaultUnlimitedAlpha207Release") {
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def packwizIndex = file("pack/packwiz/index.toml").text
|
||||
def jeiFiles = prism.files.findAll { it.path == "mods/jei-26.2-fabric-30.28.0.193.jar" }
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.anotherworld_version != "0.0.0-alpha.55"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.206"
|
||||
|| migration.source?.modules != [anotherworld: "0.0.0-alpha.54"]
|
||||
@@ -5312,9 +5312,9 @@ tasks.register("verifySafeVaultUnlimitedAlpha207Release") {
|
||||
|| migration.compatibility?.pack_release_updated != true
|
||||
|| migration.distribution?.packwiz_index_refreshed != true
|
||||
|| release.pack_version != rootProject.pack_version
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != rootProject.pack_version
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.55.jar"')
|
||||
|| packwizIndex.contains('file = "mods/anotherworld-0.0.0-alpha.54.jar"')
|
||||
|| jeiFiles.size() != 1
|
||||
@@ -5370,9 +5370,9 @@ tasks.register("verifyCanapliaFoundation") {
|
||||
"itsalive/src/main/java/fr/koka99cab/sanctuary26/itsalive/ItsAliveMod.java").text
|
||||
def visualApiSource = file(
|
||||
"ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/api/visual/AmbianceVisualEffectApi.java").text
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.36"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.19"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.21"
|
||||
|| migration.issue != 35
|
||||
|| migration.source?.fabric_id != "canaplia"
|
||||
|| migration.source?.version != "2.0.0"
|
||||
@@ -5622,8 +5622,8 @@ tasks.register("verifyCanapliaAlpha209Release") {
|
||||
ambiance: "0.0.0-alpha.14",
|
||||
itsalive: "0.0.0-alpha.33",
|
||||
onlyfun: "0.0.0-alpha.20"]
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.19"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.21"
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.36"
|
||||
|| rootProject.onlyfun_version != "0.0.0-alpha.25"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.207"
|
||||
@@ -5670,10 +5670,10 @@ tasks.register("verifyCanapliaAlpha209Release") {
|
||||
|| fixMigration.compatibility?.network_protocol_changed != false
|
||||
|| fixMigration.distribution?.pack_release_updated != true
|
||||
|| release.pack_version != rootProject.pack_version
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != rootProject.pack_version
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.19.jar"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"')
|
||||
|| !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.36.jar"')
|
||||
|| !packwizIndex.contains('file = "mods/onlyfun-0.0.0-alpha.25.jar"')
|
||||
|| packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.12.jar"')
|
||||
@@ -5723,11 +5723,11 @@ tasks.register("verifyAlpha210Release") {
|
||||
iliketomoveit: "0.0.0-alpha.15",
|
||||
itsalive: "0.0.0-alpha.35"]
|
||||
def currentModules = [
|
||||
ambiance: "0.0.0-alpha.19",
|
||||
sanctuary: "0.0.0-alpha.121",
|
||||
ambiance: "0.0.0-alpha.21",
|
||||
sanctuary: "0.0.0-alpha.122",
|
||||
onlyfun: "0.0.0-alpha.25",
|
||||
ouch: "0.0.0-alpha.10",
|
||||
iliketomoveit: "0.0.0-alpha.15",
|
||||
iliketomoveit: "0.0.0-alpha.16",
|
||||
itsalive: "0.0.0-alpha.36"]
|
||||
def requiredJars = currentModules.collect { id, version ->
|
||||
"file = \"mods/${id}-${version}.jar\""
|
||||
@@ -5740,10 +5740,10 @@ tasks.register("verifyAlpha210Release") {
|
||||
def jeiFiles = prism.files.findAll {
|
||||
it.path == "mods/jei-26.2-fabric-30.28.0.193.jar"
|
||||
}
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.121"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.122"
|
||||
|| rootProject.onlyfun_version != "0.0.0-alpha.25"
|
||||
|| rootProject.iliketomoveit_version != expectedTarget.iliketomoveit
|
||||
|| rootProject.iliketomoveit_version != currentModules.iliketomoveit
|
||||
|| rootProject.itsalive_version != "0.0.0-alpha.36"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.209"
|
||||
|| migration.source?.modules != expectedSource
|
||||
@@ -5786,10 +5786,10 @@ tasks.register("verifyAlpha210Release") {
|
||||
|| manifests.iliketomoveit.custom?.sanctuary26?.network_protocol != 5
|
||||
|| manifests.itsalive.custom?.sanctuary26?.data_version != 3
|
||||
|| manifests.itsalive.custom?.sanctuary26?.network_protocol != 4
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| requiredJars.any { !packwizIndex.contains(it) }
|
||||
|| obsoleteJars.any { packwizIndex.contains(it) }
|
||||
|| jeiFiles.size() != 1
|
||||
@@ -5836,10 +5836,11 @@ tasks.register("verifyAlpha211Release") {
|
||||
ouch: "0.0.0-alpha.10",
|
||||
sanctuary: "0.0.0-alpha.119"]
|
||||
def currentModules = expectedTarget + [
|
||||
sanctuary: "0.0.0-alpha.121",
|
||||
sanctuary: "0.0.0-alpha.122",
|
||||
onlyfun: "0.0.0-alpha.25",
|
||||
ambiance: "0.0.0-alpha.19"]
|
||||
def workspaceModules = currentModules + [ambiance: "0.0.0-alpha.19"]
|
||||
ambiance: "0.0.0-alpha.21",
|
||||
iliketomoveit: "0.0.0-alpha.16"]
|
||||
def workspaceModules = currentModules
|
||||
def expectedDataVersions = [ambiance: 2, itsalive: 3, onlyfun: 2, ouch: 1, sanctuary: 11]
|
||||
def expectedProtocols = [ambiance: 6, itsalive: 4, onlyfun: 3, ouch: 1, sanctuary: 22]
|
||||
def manifests = expectedTarget.collectEntries { id, version ->
|
||||
@@ -5864,7 +5865,7 @@ tasks.register("verifyAlpha211Release") {
|
||||
def jeiFiles = prism.files.findAll {
|
||||
it.path == "mods/jei-26.2-fabric-30.28.0.193.jar"
|
||||
}
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| workspaceModules.any { id, version -> rootProject.property("${id}_version") != version }
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.210"
|
||||
|| migration.source?.modules != expectedSource
|
||||
@@ -5892,9 +5893,9 @@ tasks.register("verifyAlpha211Release") {
|
||||
|| migration.distribution?.prism_modrinth_index_updated != true
|
||||
|| migration.distribution?.shared_client_server_mrpack != true
|
||||
|| release.pack_version != rootProject.pack_version
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != rootProject.pack_version
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| requiredJars.any { !packwizIndex.contains(it) }
|
||||
|| obsoleteJars.any { packwizIndex.contains(it) }
|
||||
|| prism.files?.size() != 5
|
||||
@@ -5902,7 +5903,7 @@ tasks.register("verifyAlpha211Release") {
|
||||
|| jeiFiles[0].hashes?.sha1 != "494f9dc787d6c9cd9d32793da2784ab16834faf3"
|
||||
|| jeiFiles[0].hashes?.sha512 != "0869f4d5840a732a04bedc7684b40140f087f3d759066c206d9d1ec710007f7c9585e4f5ebb04f10e56bef1cf2eddc6978bb2b2c93541cff5fcf7e1609859468"
|
||||
|| !changelog.contains("## `26.2.0-alpha.211`")
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.217`**")) {
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.219`**")) {
|
||||
throw new GradleException("The alpha.211 Abjection and gameplay-polish release is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -5936,8 +5937,8 @@ tasks.register("verifyAlpha212Release") {
|
||||
def jeiFiles = prism.files.findAll {
|
||||
it.path == "mods/jei-26.2-fabric-30.28.0.193.jar"
|
||||
}
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.121"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.sanctuary_version != "0.0.0-alpha.122"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.211"
|
||||
|| migration.source?.modules != [sanctuary: "0.0.0-alpha.119"]
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.212"
|
||||
@@ -5958,16 +5959,16 @@ tasks.register("verifyAlpha212Release") {
|
||||
|| manifest.custom?.sanctuary26?.data_version != 11
|
||||
|| manifest.custom?.sanctuary26?.network_protocol != 22
|
||||
|| !minecraftMixin.contains('method = "pickBlockOrEntity"')
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| prism.files?.size() != 5
|
||||
|| jeiFiles.size() != 1
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.121.jar"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.122.jar"')
|
||||
|| packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.119.jar"')
|
||||
|| !changelog.contains("## `26.2.0-alpha.212`")
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.217`**")) {
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.219`**")) {
|
||||
throw new GradleException("The alpha.212 Black Market startup-fix release is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -6001,8 +6002,8 @@ tasks.register("verifyAlpha213Release") {
|
||||
def jeiFiles = prism.files.findAll {
|
||||
it.path == "mods/jei-26.2-fabric-30.28.0.193.jar"
|
||||
}
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.19"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.21"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.212"
|
||||
|| migration.source?.modules != [ambiance: "0.0.0-alpha.15"]
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.213"
|
||||
@@ -6025,16 +6026,16 @@ tasks.register("verifyAlpha213Release") {
|
||||
|| manifest.custom?.sanctuary26?.network_protocol != 6
|
||||
|| !levelEventMixin.contains('@Mixin(LevelEventHandler.class)')
|
||||
|| !levelEventMixin.contains('@Inject(method = "levelEvent"')
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| prism.files?.size() != 5
|
||||
|| jeiFiles.size() != 1
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.19.jar"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"')
|
||||
|| packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.15.jar"')
|
||||
|| !changelog.contains("## `26.2.0-alpha.213`")
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.217`**")) {
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.219`**")) {
|
||||
throw new GradleException("The alpha.213 Ambiance startup-fix release is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -6069,8 +6070,8 @@ tasks.register("verifyAlpha214Release") {
|
||||
"ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscAudioPlayer.java").text
|
||||
def urlSmoke = file(
|
||||
"ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/white_disc/WhiteDiscUrlSmoke.java").text
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.19"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.21"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.213"
|
||||
|| migration.source?.modules != [ambiance: "0.0.0-alpha.16"]
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.214"
|
||||
@@ -6098,16 +6099,16 @@ tasks.register("verifyAlpha214Release") {
|
||||
|| !audioPlayer.contains('message.ambiance.white_disc.loading')
|
||||
|| !audioPlayer.contains('message.ambiance.white_disc.failed')
|
||||
|| !urlSmoke.contains("https://youtu.be/Ue5ZBe-GzSM?si=78LSbtBQzUYzhA2Y")
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| prism.files?.size() != 5
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.19.jar"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"')
|
||||
|| packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.16.jar"')
|
||||
|| !changelog.contains("## `26.2.0-alpha.214`")
|
||||
|| changelog.contains("## Modifications non distribuées")
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.217`**")) {
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.219`**")) {
|
||||
throw new GradleException("The alpha.214 white-disc solo synchronization release is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -6148,8 +6149,8 @@ tasks.register("verifyAlpha215Release") {
|
||||
"ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java").text
|
||||
def playbackSmoke = file(
|
||||
"ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java").text
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.19"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.21"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.214"
|
||||
|| migration.source?.modules != [ambiance: "0.0.0-alpha.17"]
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.215"
|
||||
@@ -6184,19 +6185,20 @@ tasks.register("verifyAlpha215Release") {
|
||||
|| !audioStream.contains("INITIAL_FRAME_WAIT_MILLIS = 2_000L")
|
||||
|| !audioStream.contains("CONTINUATION_FRAME_WAIT_MILLIS = 250L")
|
||||
|| !audioStream.contains("player.provide(waitMillis, TimeUnit.MILLISECONDS)")
|
||||
|| !audioStream.contains("while (output.hasRemaining()) output.put((byte) 0)")
|
||||
|| !audioStream.contains("paddedSilenceBytes++")
|
||||
|| !playbackSmoke.contains("https://www.youtube.com/watch?v=Ue5ZBe-GzSM")
|
||||
|| !playbackSmoke.contains("Decoded audible PCM data")
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| !playbackSmoke.contains("stream.paddedSilenceBytes() != 0L")
|
||||
|| !playbackSmoke.contains("stream.decodedTimelineMillis() != 4_000L")
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| prism.files?.size() != 5
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.19.jar"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"')
|
||||
|| packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.17.jar"')
|
||||
|| !changelog.contains("## `26.2.0-alpha.215`")
|
||||
|| changelog.contains("## Modifications non distribuées")
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.217`**")) {
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.219`**")) {
|
||||
throw new GradleException("The alpha.215 resilient white-disc playback release is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -6241,8 +6243,8 @@ tasks.register("verifyAlpha216Release") {
|
||||
"ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStreamSmoke.java").text
|
||||
def playbackSmoke = file(
|
||||
"ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java").text
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.19"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.21"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.215"
|
||||
|| migration.source?.modules != [ambiance: "0.0.0-alpha.18"]
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.216"
|
||||
@@ -6272,7 +6274,7 @@ tasks.register("verifyAlpha216Release") {
|
||||
|| manifest.custom?.sanctuary26?.data_version != 2
|
||||
|| manifest.custom?.sanctuary26?.network_protocol != 6
|
||||
|| !ambianceBuild.contains('tasks.register("whiteDiscStreamSmoke"')
|
||||
|| !audioPlayer.contains("channel.setPitch(1.0F)")
|
||||
|| !audioPlayer.contains("PLAYBACK_PITCH = 4.0F / 3.0F")
|
||||
|| !audioStream.contains("SAMPLE_RATE = 48_000")
|
||||
|| !audioStream.contains("INITIAL_FRAME_WAIT_MILLIS = 2_000L")
|
||||
|| !audioStream.contains("CONTINUATION_FRAME_WAIT_MILLIS = 250L")
|
||||
@@ -6280,18 +6282,19 @@ tasks.register("verifyAlpha216Release") {
|
||||
|| !audioStream.contains("new AudioFormat(SAMPLE_RATE, 16, 1, true, false)")
|
||||
|| !streamSmoke.contains("FRAMES_PER_SECOND")
|
||||
|| !streamSmoke.contains("PCM frames were not read with bounded waits")
|
||||
|| !playbackSmoke.contains("audibleRatio < 0.75")
|
||||
|| !playbackSmoke.contains("stream.paddedSilenceBytes() != 0L")
|
||||
|| !playbackSmoke.contains("stream.decodedTimelineMillis() != 4_000L")
|
||||
|| !playbackSmoke.contains("LavaplayerAudioStream.SAMPLE_RATE * 2 * 4")
|
||||
|| release.pack_version != "26.2.0-alpha.217"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.217"
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| prism.files?.size() != 5
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.19.jar"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"')
|
||||
|| packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.18.jar"')
|
||||
|| !changelog.contains("## `26.2.0-alpha.216`")
|
||||
|| changelog.contains("## Modifications non distribuées")
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.217`**")) {
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.219`**")) {
|
||||
throw new GradleException("The alpha.216 white-disc audio-quality release is incomplete")
|
||||
}
|
||||
}
|
||||
@@ -6299,8 +6302,83 @@ tasks.register("verifyAlpha216Release") {
|
||||
|
||||
tasks.register("verifyAlpha217Release") {
|
||||
group = "verification"
|
||||
description = "Checks the Sanctuary 26.2.0-alpha.217 Storage Terminal release."
|
||||
inputs.file(file("pack/migrations/26.2.0-alpha.216-storage-terminal-to-alpha.217.json"))
|
||||
description = "Checks the Sanctuary 26.2.0-alpha.217 white-disc pitch release."
|
||||
inputs.file(file("pack/migrations/26.2.0-alpha.216-white-disc-pitch-to-alpha.217.json"))
|
||||
inputs.file(file("pack/release.json"))
|
||||
inputs.file(file("pack/prism/modrinth.index.json"))
|
||||
inputs.file(file("pack/packwiz/pack.toml"))
|
||||
inputs.file(file("pack/packwiz/index.toml"))
|
||||
inputs.file(file("CHANGELOG.md"))
|
||||
inputs.file(file("README.md"))
|
||||
inputs.file(file("ambiance/src/main/resources/fabric.mod.json"))
|
||||
inputs.file(file(
|
||||
"ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscAudioPlayer.java"))
|
||||
inputs.file(file(
|
||||
"ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStreamSmoke.java"))
|
||||
doLast {
|
||||
def migration = new JsonSlurper().parse(file(
|
||||
"pack/migrations/26.2.0-alpha.216-white-disc-pitch-to-alpha.217.json"))
|
||||
def release = new JsonSlurper().parse(file("pack/release.json"))
|
||||
def prism = new JsonSlurper().parse(file("pack/prism/modrinth.index.json"))
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def packwizIndex = file("pack/packwiz/index.toml").text
|
||||
def changelog = file("CHANGELOG.md").text
|
||||
def readme = file("README.md").text
|
||||
def manifest = new JsonSlurper().parse(file("ambiance/src/main/resources/fabric.mod.json"))
|
||||
def audioPlayer = file(
|
||||
"ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscAudioPlayer.java").text
|
||||
def streamSmoke = file(
|
||||
"ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStreamSmoke.java").text
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| rootProject.ambiance_version != "0.0.0-alpha.21"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.216"
|
||||
|| migration.source?.modules != [ambiance: "0.0.0-alpha.19"]
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.217"
|
||||
|| migration.target?.modules != [ambiance: "0.0.0-alpha.20"]
|
||||
|| migration.features?.white_disc_pitch_corrected != true
|
||||
|| migration.features?.youtube_source_format != "MP4_AAC_LC"
|
||||
|| migration.features?.openal_pitch_numerator != 4
|
||||
|| migration.features?.openal_pitch_denominator != 3
|
||||
|| migration.features?.openal_pitch_reapplied_during_playback != true
|
||||
|| migration.features?.reference_video_id != "Ue5ZBe-GzSM"
|
||||
|| migration.features?.direct_source_comparison != true
|
||||
|| migration.features?.decoded_sample_rate_hz != 48_000
|
||||
|| migration.features?.decoded_channel_count != 1
|
||||
|| migration.features?.decoded_sample_size_bits != 16
|
||||
|| migration.compatibility?.new_world_required != false
|
||||
|| migration.compatibility?.save_reset_required != false
|
||||
|| migration.compatibility?.existing_saves_supported != true
|
||||
|| migration.compatibility?.registry_ids_changed != false
|
||||
|| migration.compatibility?.ambiance_data_version != 2
|
||||
|| migration.compatibility?.ambiance_network_protocol != 6
|
||||
|| migration.distribution?.pack_release_updated != true
|
||||
|| migration.distribution?.packwiz_index_refreshed != true
|
||||
|| migration.distribution?.prism_modrinth_index_updated != true
|
||||
|| migration.distribution?.shared_client_server_mrpack != true
|
||||
|| manifest.custom?.sanctuary26?.data_version != 2
|
||||
|| manifest.custom?.sanctuary26?.network_protocol != 6
|
||||
|| !audioPlayer.contains("PLAYBACK_PITCH = 4.0F / 3.0F")
|
||||
|| audioPlayer.count("channel.setPitch(PLAYBACK_PITCH)") != 2
|
||||
|| !streamSmoke.contains("WhiteDiscAudioPlayer.PLAYBACK_PITCH - 4.0F / 3.0F")
|
||||
|| release.pack_version != "26.2.0-alpha.219"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != "26.2.0-alpha.219"
|
||||
|| prism.files?.size() != 5
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"')
|
||||
|| packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.19.jar"')
|
||||
|| !changelog.contains("## `26.2.0-alpha.217`")
|
||||
|| changelog.contains("## Modifications non distribuées")
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.219`**")) {
|
||||
throw new GradleException("The alpha.217 white-disc pitch release is incomplete")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("verifyAlpha218Release") {
|
||||
group = "verification"
|
||||
description = "Checks the Sanctuary 26.2.0-alpha.218 Storage Terminal release."
|
||||
inputs.file(file("pack/migrations/26.2.0-alpha.217-storage-terminal-to-alpha.218.json"))
|
||||
inputs.file(file("pack/release.json"))
|
||||
inputs.file(file("pack/prism/modrinth.index.json"))
|
||||
inputs.file(file("pack/packwiz/pack.toml"))
|
||||
@@ -6316,7 +6394,7 @@ tasks.register("verifyAlpha217Release") {
|
||||
inputs.file(file("sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/BlackMarketItemPolicy.java"))
|
||||
doLast {
|
||||
def migration = new JsonSlurper().parse(file(
|
||||
"pack/migrations/26.2.0-alpha.216-storage-terminal-to-alpha.217.json"))
|
||||
"pack/migrations/26.2.0-alpha.217-storage-terminal-to-alpha.218.json"))
|
||||
def release = new JsonSlurper().parse(file("pack/release.json"))
|
||||
def prism = new JsonSlurper().parse(file("pack/prism/modrinth.index.json"))
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
@@ -6338,17 +6416,19 @@ tasks.register("verifyAlpha217Release") {
|
||||
redstoner: "0.0.0-alpha.10", onlyfun: "0.0.0-alpha.24", sanctuary: "0.0.0-alpha.120"]
|
||||
def targetModules = [
|
||||
redstoner: "0.0.0-alpha.11", onlyfun: "0.0.0-alpha.25", sanctuary: "0.0.0-alpha.121"]
|
||||
def requiredJars = targetModules.collect { id, version ->
|
||||
def currentModules = targetModules + [
|
||||
sanctuary: "0.0.0-alpha.122", iliketomoveit: "0.0.0-alpha.16", ambiance: "0.0.0-alpha.21"]
|
||||
def requiredJars = currentModules.collect { id, version ->
|
||||
"file = \"mods/${id}-${version}.jar\""
|
||||
}
|
||||
def obsoleteJars = sourceModules.collect { id, version ->
|
||||
"file = \"mods/${id}-${version}.jar\""
|
||||
}
|
||||
if (rootProject.pack_version != "26.2.0-alpha.217"
|
||||
|| targetModules.any { id, version -> rootProject.property("${id}_version") != version }
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.216"
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| currentModules.any { id, version -> rootProject.property("${id}_version") != version }
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.217"
|
||||
|| migration.source?.modules != sourceModules
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.217"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.218"
|
||||
|| migration.target?.modules != targetModules
|
||||
|| migration.storage_terminal?.id != "redstoner:storage_terminal"
|
||||
|| migration.storage_terminal?.shape_depth_pixels != 8
|
||||
@@ -6377,14 +6457,108 @@ tasks.register("verifyAlpha217Release") {
|
||||
|| !onlyFunPolicy.contains('namespace.equals("redstoner") && path.equals("storage_terminal")')
|
||||
|| !blackMarketPolicy.contains('namespace.equals("redstoner") && path.equals("storage_terminal")')
|
||||
|| release.pack_version != rootProject.pack_version
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.217.mrpack"
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != rootProject.pack_version
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.217"')
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| requiredJars.any { !packwizIndex.contains(it) }
|
||||
|| obsoleteJars.any { packwizIndex.contains(it) }
|
||||
|| !changelog.contains("## `26.2.0-alpha.217`")
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.217`**")) {
|
||||
throw new GradleException("The alpha.217 Storage Terminal release is incomplete")
|
||||
|| !changelog.contains("## `26.2.0-alpha.218`")
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.219`**")) {
|
||||
throw new GradleException("The alpha.218 Storage Terminal release is incomplete")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("verifyAlpha219Release") {
|
||||
group = "verification"
|
||||
description = "Checks the Sanctuary 26.2.0-alpha.219 finite Alpha/Indev integration release."
|
||||
inputs.file(file("pack/migrations/26.2.0-alpha.218-alpha-indev-to-alpha.219.json"))
|
||||
inputs.file(file("pack/release.json"))
|
||||
inputs.file(file("pack/prism/modrinth.index.json"))
|
||||
inputs.file(file("pack/packwiz/pack.toml"))
|
||||
inputs.file(file("pack/packwiz/index.toml"))
|
||||
inputs.file(file("CHANGELOG.md"))
|
||||
inputs.file(file("README.md"))
|
||||
inputs.file(file("sanctuary/ALPHA.md"))
|
||||
inputs.file(file("sanctuary/THIRD_PARTY_NOTICES.md"))
|
||||
inputs.file(file("iliketomoveit/PORTALS.md"))
|
||||
inputs.file(file("ambiance/GOLDEN_DAYS.md"))
|
||||
inputs.file(file("ambiance/THIRD_PARTY_NOTICES.md"))
|
||||
inputs.files(["sanctuary", "iliketomoveit", "ambiance"].collect { id ->
|
||||
file("${id}/src/main/resources/fabric.mod.json")
|
||||
})
|
||||
inputs.files(fileTree("sanctuary/src/main/resources/data/sanctuary") { include "**/alpha*.json" })
|
||||
inputs.file(file("iliketomoveit/src/main/resources/data/iliketomoveit/sanctuary_portal/alpha.json"))
|
||||
inputs.file(file(
|
||||
"ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/AlphaTexturePackManager.java"))
|
||||
doLast {
|
||||
def migration = new JsonSlurper().parse(file(
|
||||
"pack/migrations/26.2.0-alpha.218-alpha-indev-to-alpha.219.json"))
|
||||
def release = new JsonSlurper().parse(file("pack/release.json"))
|
||||
def prism = new JsonSlurper().parse(file("pack/prism/modrinth.index.json"))
|
||||
def packwiz = file("pack/packwiz/pack.toml").text
|
||||
def packwizIndex = file("pack/packwiz/index.toml").text
|
||||
def changelog = file("CHANGELOG.md").text
|
||||
def readme = file("README.md").text
|
||||
def manifests = ["sanctuary", "iliketomoveit", "ambiance"].collectEntries { id ->
|
||||
[(id): new JsonSlurper().parse(file("${id}/src/main/resources/fabric.mod.json"))]
|
||||
}
|
||||
def sourceModules = [
|
||||
sanctuary: "0.0.0-alpha.121", iliketomoveit: "0.0.0-alpha.15", ambiance: "0.0.0-alpha.20"]
|
||||
def targetModules = [
|
||||
sanctuary: "0.0.0-alpha.122", iliketomoveit: "0.0.0-alpha.16", ambiance: "0.0.0-alpha.21"]
|
||||
def requiredJars = targetModules.collect { id, version ->
|
||||
"file = \"mods/${id}-${version}.jar\""
|
||||
}
|
||||
def obsoleteJars = sourceModules.collect { id, version ->
|
||||
"file = \"mods/${id}-${version}.jar\""
|
||||
}
|
||||
def forbiddenGoldenArchives = fileTree(projectDir) {
|
||||
include "**/*golden*days*.zip", "**/*golden*days*.jar"
|
||||
exclude "**/build/**", "**/.gradle/**", "**/.git/**"
|
||||
}.files
|
||||
if (rootProject.pack_version != "26.2.0-alpha.219"
|
||||
|| targetModules.any { id, version -> rootProject.property("${id}_version") != version }
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.218"
|
||||
|| migration.source?.modules != sourceModules
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.219"
|
||||
|| migration.target?.modules != targetModules
|
||||
|| migration.alpha_world?.dimension != "sanctuary:alpha"
|
||||
|| migration.alpha_world?.width != 128 || migration.alpha_world?.depth != 128
|
||||
|| migration.alpha_world?.height != 64 || migration.alpha_world?.deterministic_per_seed != true
|
||||
|| migration.alpha_world?.legacy_identifier_migrated != true
|
||||
|| migration.alpha_portal?.schema_version != 2
|
||||
|| migration.alpha_portal?.server_authoritative_destination != true
|
||||
|| migration.alpha_portal?.server_authoritative_coordinates != true
|
||||
|| migration.alpha_portal?.remote_half_avoids_historical_house != true
|
||||
|| migration.alpha_textures?.bundled_assets != false
|
||||
|| migration.alpha_textures?.bundled_archives != false
|
||||
|| migration.alpha_textures?.previous_selection_restored_exactly != true
|
||||
|| migration.alpha_textures?.dedicated_server_files_required != false
|
||||
|| migration.compatibility?.save_reset_required != false
|
||||
|| migration.compatibility?.sanctuary_data_version != 11
|
||||
|| migration.compatibility?.sanctuary_network_protocol != 22
|
||||
|| migration.compatibility?.iliketomoveit_data_version != 3
|
||||
|| migration.compatibility?.iliketomoveit_network_protocol != 5
|
||||
|| migration.compatibility?.ambiance_data_version != 2
|
||||
|| migration.compatibility?.ambiance_network_protocol != 6
|
||||
|| manifests.sanctuary.custom?.sanctuary26?.data_version != 11
|
||||
|| manifests.sanctuary.custom?.sanctuary26?.network_protocol != 22
|
||||
|| manifests.iliketomoveit.custom?.sanctuary26?.data_version != 3
|
||||
|| manifests.iliketomoveit.custom?.sanctuary26?.network_protocol != 5
|
||||
|| manifests.ambiance.custom?.sanctuary26?.data_version != 2
|
||||
|| manifests.ambiance.custom?.sanctuary26?.network_protocol != 6
|
||||
|| release.pack_version != rootProject.pack_version
|
||||
|| release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack"
|
||||
|| prism.versionId != rootProject.pack_version
|
||||
|| prism.files.any { it.path.toLowerCase().contains("golden-days") }
|
||||
|| !packwiz.contains('version = "26.2.0-alpha.219"')
|
||||
|| requiredJars.any { !packwizIndex.contains(it) }
|
||||
|| obsoleteJars.any { packwizIndex.contains(it) }
|
||||
|| !forbiddenGoldenArchives.isEmpty()
|
||||
|| !changelog.contains("## `26.2.0-alpha.219`")
|
||||
|| !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.219`**")) {
|
||||
throw new GradleException("The alpha.219 finite Alpha/Indev release is incomplete")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6395,6 +6569,8 @@ tasks.named("verifyWorkspace") {
|
||||
dependsOn tasks.named("verifyAlpha215Release")
|
||||
dependsOn tasks.named("verifyAlpha216Release")
|
||||
dependsOn tasks.named("verifyAlpha217Release")
|
||||
dependsOn tasks.named("verifyAlpha218Release")
|
||||
dependsOn tasks.named("verifyAlpha219Release")
|
||||
}
|
||||
|
||||
tasks.named("check") {
|
||||
|
||||
+4
-4
@@ -12,7 +12,7 @@ fabric_api_version=0.158.0+26.2
|
||||
# Standby modules stay at zero until their migration really begins.
|
||||
mod_version=0.0.0-alpha.0
|
||||
module_lifecycle=standby
|
||||
ambiance_version=0.0.0-alpha.19
|
||||
ambiance_version=0.0.0-alpha.21
|
||||
ambiance_lifecycle=active
|
||||
redstoner_version=0.0.0-alpha.11
|
||||
redstoner_lifecycle=active
|
||||
@@ -24,11 +24,11 @@ ouch_version=0.0.0-alpha.10
|
||||
ouch_lifecycle=active
|
||||
masterkey_version=0.0.0-alpha.8
|
||||
masterkey_lifecycle=active
|
||||
iliketomoveit_version=0.0.0-alpha.15
|
||||
iliketomoveit_version=0.0.0-alpha.16
|
||||
iliketomoveit_lifecycle=active
|
||||
onlyfun_version=0.0.0-alpha.25
|
||||
onlyfun_lifecycle=active
|
||||
sanctuary_version=0.0.0-alpha.121
|
||||
sanctuary_version=0.0.0-alpha.122
|
||||
sanctuary_lifecycle=active
|
||||
pack_version=26.2.0-alpha.217
|
||||
pack_version=26.2.0-alpha.219
|
||||
maven_group=fr.koka99cab.sanctuary26
|
||||
|
||||
@@ -29,7 +29,7 @@ Une route est un JSON sous `data/<namespace>/sanctuary_portal/<id>.json` :
|
||||
- `arrival.type` vaut `surface`, `matched_y` ou `fixed_y`; ce dernier exige `arrival.y`.
|
||||
- `priority` départage deux routes acceptant le même cadre.
|
||||
|
||||
Les neuf routes historiques restent déclarées pour la compatibilité. Pour l'alpha.150, seules deux routes sont actives : terre vers la paire Sanctuary/Overworld et pierre vers `sanctuary:caverns`. Alpha, Sheep Land, Skeleton Waste, Lost City, Painted Canyons, Breaker Sea et Laputa restent réservées mais ne sont pas chargeables.
|
||||
Les neuf routes historiques restent déclarées pour la compatibilité. Depuis l'alpha.219, trois routes sont actives : terre vers la paire Sanctuary/Overworld, pierre vers `sanctuary:caverns` et cobblestone moussue vers `sanctuary:alpha`. Sheep Land, Skeleton Waste, Lost City, Painted Canyons, Breaker Sea et Laputa restent réservées mais ne sont pas chargeables.
|
||||
|
||||
La route en terre est la seule route v2 dynamique. Dans le profil Sanctuary, elle relie `minecraft:overworld` à `sanctuary:overworld`. Dans le profil Overworld, elle relie `minecraft:overworld` à `sanctuary:main`. Le choix appartient à la sauvegarde, jamais à une préférence cliente.
|
||||
|
||||
@@ -43,8 +43,16 @@ La route en terre est la seule route v2 dynamique. Dans le profil Sanctuary, ell
|
||||
4. Reconstruire le même cadre réactive son endpoint; la traversée suivante régénère un lien.
|
||||
5. Une destination absente refuse la traversée proprement. Elle ne crée aucune dimension et n'endommage pas la sauvegarde.
|
||||
|
||||
La route Alpha exige un cadre extérieur de 4 × 5 avec un intérieur vide de
|
||||
2 × 3, entièrement en cobblestone moussue, puis un briquet. Le serveur valide
|
||||
le cadre, l'activateur et la présence de `sanctuary:alpha` avant de l'allumer.
|
||||
Sa première moitié distante utilise l'arrivée sûre calculée par l'API publique
|
||||
de Sanctuary, hors de la maison Indev ; le client ne choisit ni la destination
|
||||
ni les coordonnées. L'Atlas découvre le bloc de portail actif comme les autres
|
||||
points d'intérêt locaux.
|
||||
|
||||
Le bloc intérieur actif est `iliketomoveit:portal`. Les neuf anciens blocs `portals:*_portal` restent enregistrés comme compatibilité de lecture; une première utilisation les rattache au nouvel index.
|
||||
|
||||
## État des générateurs
|
||||
|
||||
Le générateur principal Sanctuary et sa paire Overworld sont actifs depuis l'alpha.71. Caverns, Alpha, Sheep Land, Skeleton Waste, Lost City, Painted Canyons, Breaker Sea et Laputa restent réservés mais non générés. Leurs cadres peuvent être allumés et persistés ; une traversée vers une destination encore absente est refusée proprement.
|
||||
Le générateur principal Sanctuary et sa paire Overworld sont actifs depuis l'alpha.71. Caverns et Alpha sont également générés ; Alpha est le monde Indev fini 128 × 128 × 64 possédé par Sanctuary. Sheep Land, Skeleton Waste, Lost City, Painted Canyons, Breaker Sea et Laputa restent réservés mais non générés. Une traversée vers une destination absente est refusée proprement dès l'allumage.
|
||||
|
||||
@@ -24,6 +24,14 @@ tasks.register("happyGhastCruiseSpeedSmoke", JavaExec) {
|
||||
dependsOn tasks.named("testClasses")
|
||||
}
|
||||
|
||||
tasks.register("alphaPortalContractSmoke", JavaExec) {
|
||||
group = "verification"
|
||||
description = "Checks the active Alpha route and its finite-world safe-arrival contract."
|
||||
classpath = sourceSets.test.runtimeClasspath
|
||||
mainClass = "fr.koka99cab.sanctuary26.iliketomoveit.portal.AlphaPortalContractSmoke"
|
||||
dependsOn tasks.named("testClasses")
|
||||
}
|
||||
|
||||
tasks.named("test") {
|
||||
// Runtime contracts are executable smoke tasks, not JUnit engine tests.
|
||||
failOnNoDiscoveredTests = false
|
||||
@@ -268,7 +276,7 @@ tasks.register("verifyPortals") {
|
||||
def routeFile = file("src/main/resources/data/iliketomoveit/sanctuary_portal/${route}.json")
|
||||
if (!routeFile.isFile()) throw new GradleException("Missing portal route ${route}")
|
||||
def json = new JsonSlurper().parse(routeFile)
|
||||
def expectedSchema = route == 'overworld' ? 2 : 1
|
||||
def expectedSchema = route in ['overworld', 'alpha'] ? 2 : 1
|
||||
if (json.schema_version != expectedSchema || json.destination_dimension != destination
|
||||
|| json.source_dimension != "minecraft:overworld"
|
||||
|| (route == 'overworld' && json.destination_resolver != "overworld_pair")
|
||||
@@ -305,7 +313,7 @@ tasks.register("verifyPortals") {
|
||||
}
|
||||
def atlasCavernsMigration = new JsonSlurper().parse(rootProject.file(
|
||||
"pack/migrations/26.2.0-alpha.149-atlas-caverns-to-alpha.150.json"))
|
||||
if (project.version.toString() != "0.0.0-alpha.15"
|
||||
if (project.version.toString() != "0.0.0-alpha.16"
|
||||
|| atlasCavernsMigration.target?.pack_version != "26.2.0-alpha.150"
|
||||
|| atlasCavernsMigration.target?.modules?.iliketomoveit != "0.0.0-alpha.9"
|
||||
|| atlasCavernsMigration.portals?.active_routes != [
|
||||
@@ -313,7 +321,7 @@ tasks.register("verifyPortals") {
|
||||
|| atlasCavernsMigration.portals?.inactive_routes?.size() != 7
|
||||
|| atlasCavernsMigration.portals?.reserved_ids_retained != true
|
||||
|| atlasCavernsMigration.portals?.inactive_routes_loadable != false
|
||||
|| !javaText.contains("ACTIVE_ROUTES = List.of(OVERWORLD, CAVERNS)")
|
||||
|| !javaText.contains("ACTIVE_ROUTES = List.of(OVERWORLD, CAVERNS, ALPHA)")
|
||||
|| !javaText.contains("REQUIRED_ROUTES = ACTIVE_ROUTES")
|
||||
|| atlasCavernsMigration.compatibility?.iliketomoveit_data_version != 3
|
||||
|| atlasCavernsMigration.compatibility?.iliketomoveit_network_protocol != 3) {
|
||||
@@ -341,7 +349,7 @@ tasks.register("verifySilverAircraft") {
|
||||
def manifest = new JsonSlurper().parse(file("src/main/resources/fabric.mod.json"))
|
||||
def migration = new JsonSlurper().parse(rootProject.file(
|
||||
"pack/migrations/26.2.0-alpha.184-silver-engineering-to-alpha.185.json"))
|
||||
if (project.version.toString() != "0.0.0-alpha.15"
|
||||
if (project.version.toString() != "0.0.0-alpha.16"
|
||||
|| recipe.pattern != ["PGP", "GCG", "PBP"]
|
||||
|| recipe.key != [B: "anotherworld:silver_block", C: "anotherworld:aircraft_cockpit",
|
||||
G: "anotherworld:silver_gear", P: "anotherworld:silver_plate"]
|
||||
@@ -370,7 +378,7 @@ tasks.register("verifyGrapplePrediction") {
|
||||
def payload = file("src/main/java/fr/koka99cab/sanctuary26/iliketomoveit/network/GrappleStatePayload.java").text
|
||||
def controller = file("src/main/java/fr/koka99cab/sanctuary26/iliketomoveit/grapple/GrappleController.java").text
|
||||
def prediction = file("src/main/java/fr/koka99cab/sanctuary26/iliketomoveit/client/grapple/ClientGrapplePrediction.java").text
|
||||
if (project.version.toString() != "0.0.0-alpha.15"
|
||||
if (project.version.toString() != "0.0.0-alpha.16"
|
||||
|| migration.target?.modules?.iliketomoveit != "0.0.0-alpha.13"
|
||||
|| migration.grappling?.owner_prediction_payload != "iliketomoveit:s2c/grapple_state"
|
||||
|| migration.compatibility?.iliketomoveit_source_network_protocol != 4
|
||||
@@ -402,7 +410,7 @@ tasks.register("verifyWaystoneDescendingRelease") {
|
||||
"src/main/java/fr/koka99cab/sanctuary26/iliketomoveit/waystone/WaystoneElevatorRules.java").text
|
||||
def teleportation = file(
|
||||
"src/main/java/fr/koka99cab/sanctuary26/iliketomoveit/network/WaystoneTeleportation.java").text
|
||||
if (project.version.toString() != "0.0.0-alpha.15"
|
||||
if (project.version.toString() != "0.0.0-alpha.16"
|
||||
|| migration.target?.modules?.iliketomoveit != "0.0.0-alpha.14"
|
||||
|| migration.waystone_elevator?.undiscovered_downward_destination_allowed != true
|
||||
|| migration.waystone_elevator?.destination_discovered_after_arrival != true
|
||||
@@ -418,6 +426,44 @@ tasks.register("verifyWaystoneDescendingRelease") {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("verifyAlphaPortal") {
|
||||
group = "verification"
|
||||
description = "Checks the alpha.16 mossy Alpha portal lifecycle and server authority."
|
||||
inputs.file(file("PORTALS.md"))
|
||||
inputs.file(file("src/main/resources/data/iliketomoveit/sanctuary_portal/alpha.json"))
|
||||
inputs.files(fileTree("src/main/resources/assets/iliketomoveit/lang") { include "*.json" })
|
||||
inputs.files(fileTree("src/main/java/fr/koka99cab/sanctuary26/iliketomoveit/portal") { include "*.java" })
|
||||
inputs.file(rootProject.file("pack/migrations/26.2.0-alpha.218-alpha-indev-to-alpha.219.json"))
|
||||
doLast {
|
||||
def route = new JsonSlurper().parse(file(
|
||||
"src/main/resources/data/iliketomoveit/sanctuary_portal/alpha.json"))
|
||||
def migration = new JsonSlurper().parse(rootProject.file(
|
||||
"pack/migrations/26.2.0-alpha.218-alpha-indev-to-alpha.219.json"))
|
||||
def javaText = fileTree("src/main/java/fr/koka99cab/sanctuary26/iliketomoveit/portal")
|
||||
.matching { include "*.java" }.files*.text.join("\n")
|
||||
def locales = ["fr_fr", "en_us", "ru_ru"].collect {
|
||||
new JsonSlurper().parse(file("src/main/resources/assets/iliketomoveit/lang/${it}.json"))
|
||||
}
|
||||
if (project.version.toString() != "0.0.0-alpha.16"
|
||||
|| route.schema_version != 2 || route.source_dimension != "minecraft:overworld"
|
||||
|| route.destination_dimension != "sanctuary:alpha"
|
||||
|| route.destination_resolver != "fixed"
|
||||
|| route.frame_blocks != ["minecraft:mossy_cobblestone"]
|
||||
|| route.activation_items != ["minecraft:flint_and_steel"]
|
||||
|| migration.alpha_portal?.outer_width != 4 || migration.alpha_portal?.outer_height != 5
|
||||
|| migration.alpha_portal?.inner_width != 2 || migration.alpha_portal?.inner_height != 3
|
||||
|| migration.alpha_portal?.inactive_when_destination_absent != true
|
||||
|| migration.alpha_portal?.persistent_pair_reused != true
|
||||
|| migration.alpha_portal?.break_unlinks_pair != true
|
||||
|| !javaText.contains("ACTIVE_ROUTES = List.of(OVERWORLD, CAVERNS, ALPHA)")
|
||||
|| !javaText.contains("SanctuaryAlphaWorld.portalArrival(targetLevel.getSeed())")
|
||||
|| !javaText.contains("getServer().getLevel(")
|
||||
|| locales.any { !it.containsKey("message.iliketomoveit.portal.destination_unavailable") }) {
|
||||
throw new GradleException("I Like To Move It alpha.16 Alpha portal contract is incomplete")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("check") {
|
||||
dependsOn tasks.named("grapplePhysicsSmoke")
|
||||
dependsOn tasks.named("waystoneElevatorRulesSmoke")
|
||||
@@ -428,4 +474,6 @@ tasks.named("check") {
|
||||
dependsOn tasks.named("verifyWaystoneDescendingRelease")
|
||||
dependsOn tasks.named("verifyPortals")
|
||||
dependsOn tasks.named("verifySilverAircraft")
|
||||
dependsOn tasks.named("alphaPortalContractSmoke")
|
||||
dependsOn tasks.named("verifyAlphaPortal")
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ public final class PortalDefinitions {
|
||||
public static final Identifier LAPUTA = ILikeToMoveItMod.id("laputa");
|
||||
|
||||
/** Routes enabled for the current gameplay milestone. Other stable IDs stay reserved. */
|
||||
public static final List<Identifier> ACTIVE_ROUTES = List.of(OVERWORLD, CAVERNS);
|
||||
public static final List<Identifier> ACTIVE_ROUTES = List.of(OVERWORLD, CAVERNS, ALPHA);
|
||||
public static final List<Identifier> REQUIRED_ROUTES = ACTIVE_ROUTES;
|
||||
|
||||
private static volatile Map<Identifier, PortalDefinition> definitions = Map.of();
|
||||
|
||||
+7
@@ -4,6 +4,7 @@ import fr.koka99cab.sanctuary26.iliketomoveit.registry.ILikeToMoveItBlocks;
|
||||
import java.util.Optional;
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
@@ -37,6 +38,12 @@ public final class PortalIgnitionHandler {
|
||||
}
|
||||
|
||||
ServerLevel serverLevel = (ServerLevel) level;
|
||||
if (serverLevel.getServer().getLevel(
|
||||
selected.targetDimension(serverLevel.getServer(), serverLevel.dimension())) == null) {
|
||||
player.sendOverlayMessage(Component.translatable(
|
||||
"message.iliketomoveit.portal.destination_unavailable"));
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
PortalEndpoint endpoint = PortalSavedData.get(serverLevel.getServer())
|
||||
.register(serverLevel, selectedFrame, selected.id());
|
||||
selectedFrame.fill(serverLevel, selected, endpoint, ILikeToMoveItBlocks.PORTAL);
|
||||
|
||||
+5
@@ -3,6 +3,8 @@ package fr.koka99cab.sanctuary26.iliketomoveit.portal;
|
||||
import fr.koka99cab.sanctuary26.iliketomoveit.ILikeToMoveItMod;
|
||||
import fr.koka99cab.sanctuary26.iliketomoveit.block.PortalBlock;
|
||||
import fr.koka99cab.sanctuary26.iliketomoveit.registry.ILikeToMoveItBlocks;
|
||||
import fr.koka99cab.sanctuary26.sanctuary.api.world.SanctuaryAlphaWorld;
|
||||
import fr.koka99cab.sanctuary26.sanctuary.world.SanctuaryDimensions;
|
||||
import java.util.Optional;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -92,6 +94,9 @@ public final class PortalTeleporter {
|
||||
|
||||
private static BlockPos targetCenter(ServerLevel sourceLevel, ServerLevel targetLevel,
|
||||
PortalFrame sourceFrame, PortalDefinition definition) {
|
||||
if (targetLevel.dimension().equals(SanctuaryDimensions.ALPHA)) {
|
||||
return SanctuaryAlphaWorld.portalArrival(targetLevel.getSeed());
|
||||
}
|
||||
double scale = definition.scaleFrom(sourceLevel.dimension());
|
||||
int x = Mth.floor(sourceFrame.center().getX() * scale);
|
||||
int z = Mth.floor(sourceFrame.center().getZ() * scale);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"schema_version": 2,
|
||||
"source_dimension": "minecraft:overworld",
|
||||
"destination_dimension": "sanctuary:alpha",
|
||||
"destination_resolver": "fixed",
|
||||
"frame_blocks": ["minecraft:mossy_cobblestone"],
|
||||
"preferred_frame_block": "minecraft:mossy_cobblestone",
|
||||
"activation_items": ["minecraft:flint_and_steel"],
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package fr.koka99cab.sanctuary26.iliketomoveit.portal;
|
||||
|
||||
import fr.koka99cab.sanctuary26.sanctuary.api.world.SanctuaryAlphaWorld;
|
||||
import java.util.Set;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
|
||||
/** Executable cross-module contract for the active mossy Alpha portal. */
|
||||
public final class AlphaPortalContractSmoke {
|
||||
private AlphaPortalContractSmoke() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SharedConstants.tryDetectVersion();
|
||||
Bootstrap.bootStrap();
|
||||
require(PortalDefinitions.ACTIVE_ROUTES.equals(PortalDefinitions.REQUIRED_ROUTES),
|
||||
"Every active portal definition must be required at reload");
|
||||
require(Set.copyOf(PortalDefinitions.ACTIVE_ROUTES).equals(Set.of(
|
||||
PortalDefinitions.OVERWORLD, PortalDefinitions.CAVERNS, PortalDefinitions.ALPHA)),
|
||||
"Exactly the Overworld, Caverns and Alpha routes must be active");
|
||||
|
||||
for (long seed : new long[] { 0L, 1L, 46L }) {
|
||||
BlockPos arrival = SanctuaryAlphaWorld.portalArrival(seed);
|
||||
BlockPos residence = SanctuaryAlphaWorld.residence(seed);
|
||||
require(SanctuaryAlphaWorld.containsHorizontal(arrival),
|
||||
"Server-selected Alpha arrival must stay inside the finite island");
|
||||
require(Math.max(Math.abs(arrival.getX() - residence.getX()),
|
||||
Math.abs(arrival.getZ() - residence.getZ())) >= 10,
|
||||
"The remote portal must not damage the Indev residence");
|
||||
}
|
||||
}
|
||||
|
||||
private static void require(boolean condition, String message) {
|
||||
if (!condition) throw new AssertionError(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"source": {
|
||||
"pack_version": "26.2.0-alpha.216",
|
||||
"modules": {
|
||||
"ambiance": "0.0.0-alpha.19"
|
||||
}
|
||||
},
|
||||
"target": {
|
||||
"pack_version": "26.2.0-alpha.217",
|
||||
"modules": {
|
||||
"ambiance": "0.0.0-alpha.20"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"white_disc_pitch_corrected": true,
|
||||
"youtube_source_format": "MP4_AAC_LC",
|
||||
"openal_pitch_numerator": 4,
|
||||
"openal_pitch_denominator": 3,
|
||||
"openal_pitch_reapplied_during_playback": true,
|
||||
"reference_video_id": "Ue5ZBe-GzSM",
|
||||
"direct_source_comparison": true,
|
||||
"decoded_sample_rate_hz": 48000,
|
||||
"decoded_channel_count": 1,
|
||||
"decoded_sample_size_bits": 16
|
||||
},
|
||||
"compatibility": {
|
||||
"new_world_required": false,
|
||||
"save_reset_required": false,
|
||||
"existing_saves_supported": true,
|
||||
"registry_ids_changed": false,
|
||||
"ambiance_data_version": 2,
|
||||
"ambiance_network_protocol": 6
|
||||
},
|
||||
"distribution": {
|
||||
"pack_release_updated": true,
|
||||
"packwiz_index_refreshed": true,
|
||||
"prism_modrinth_index_updated": true,
|
||||
"shared_client_server_mrpack": true
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"source": {
|
||||
"pack_version": "26.2.0-alpha.216",
|
||||
"pack_version": "26.2.0-alpha.217",
|
||||
"modules": {
|
||||
"redstoner": "0.0.0-alpha.10",
|
||||
"onlyfun": "0.0.0-alpha.24",
|
||||
@@ -9,7 +9,7 @@
|
||||
}
|
||||
},
|
||||
"target": {
|
||||
"pack_version": "26.2.0-alpha.217",
|
||||
"pack_version": "26.2.0-alpha.218",
|
||||
"modules": {
|
||||
"redstoner": "0.0.0-alpha.11",
|
||||
"onlyfun": "0.0.0-alpha.25",
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"source": {
|
||||
"pack_version": "26.2.0-alpha.218",
|
||||
"modules": {
|
||||
"sanctuary": "0.0.0-alpha.121",
|
||||
"iliketomoveit": "0.0.0-alpha.15",
|
||||
"ambiance": "0.0.0-alpha.20"
|
||||
}
|
||||
},
|
||||
"target": {
|
||||
"pack_version": "26.2.0-alpha.219",
|
||||
"modules": {
|
||||
"sanctuary": "0.0.0-alpha.122",
|
||||
"iliketomoveit": "0.0.0-alpha.16",
|
||||
"ambiance": "0.0.0-alpha.21"
|
||||
}
|
||||
},
|
||||
"alpha_world": {
|
||||
"owner": "sanctuary",
|
||||
"dimension": "sanctuary:alpha",
|
||||
"legacy_dimension": "portals:alpha",
|
||||
"legacy_identifier_migrated": true,
|
||||
"width": 128,
|
||||
"depth": 128,
|
||||
"height": 64,
|
||||
"minimum_xz": -64,
|
||||
"maximum_xz": 63,
|
||||
"deterministic_per_seed": true,
|
||||
"finite_barrier_boundary": true,
|
||||
"bedrock_floor": true,
|
||||
"historical_house": true,
|
||||
"historical_residence_exposed_by_api": true,
|
||||
"safe_portal_arrival_exposed_by_api": true,
|
||||
"registered_profiles": ["sanctuary", "overworld"],
|
||||
"dedicated_server_supported": true
|
||||
},
|
||||
"alpha_portal": {
|
||||
"owner": "iliketomoveit",
|
||||
"route": "iliketomoveit:alpha",
|
||||
"schema_version": 2,
|
||||
"frame_block": "minecraft:mossy_cobblestone",
|
||||
"outer_width": 4,
|
||||
"outer_height": 5,
|
||||
"inner_width": 2,
|
||||
"inner_height": 3,
|
||||
"activation_item": "minecraft:flint_and_steel",
|
||||
"inactive_when_destination_absent": true,
|
||||
"server_authoritative_destination": true,
|
||||
"server_authoritative_coordinates": true,
|
||||
"persistent_pair_reused": true,
|
||||
"break_unlinks_pair": true,
|
||||
"remote_half_avoids_historical_house": true,
|
||||
"atlas_discovery_supported": true
|
||||
},
|
||||
"alpha_textures": {
|
||||
"owner": "ambiance",
|
||||
"client_only": true,
|
||||
"destination": "sanctuary:alpha",
|
||||
"bundled_assets": false,
|
||||
"bundled_archives": false,
|
||||
"external_packs": ["Golden Days Base", "Golden Days Alpha"],
|
||||
"overlay_order": ["base", "alpha"],
|
||||
"previous_selection_restored_exactly": true,
|
||||
"saved_options_modified": false,
|
||||
"missing_packs_fallback": "vanilla",
|
||||
"dedicated_server_files_required": false,
|
||||
"official_base_url": "https://www.curseforge.com/minecraft/texture-packs/golden-days",
|
||||
"official_alpha_url": "https://www.curseforge.com/minecraft/texture-packs/golden-days-alpha",
|
||||
"official_license_url": "https://poeticrainbow.github.io/golden-days/license/"
|
||||
},
|
||||
"compatibility": {
|
||||
"new_world_required": false,
|
||||
"save_reset_required": false,
|
||||
"existing_saves_supported": true,
|
||||
"sanctuary_data_version": 11,
|
||||
"sanctuary_network_protocol": 22,
|
||||
"iliketomoveit_data_version": 3,
|
||||
"iliketomoveit_network_protocol": 5,
|
||||
"ambiance_data_version": 2,
|
||||
"ambiance_network_protocol": 6
|
||||
},
|
||||
"distribution": {
|
||||
"pack_release_updated": true,
|
||||
"packwiz_index_refreshed": true,
|
||||
"prism_modrinth_index_updated": true,
|
||||
"golden_days_assets_in_mrpack": false,
|
||||
"shared_client_server_mrpack": true
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -13,16 +13,16 @@ file = "instance-icon.png"
|
||||
hash = "41f4f4c88c71d0a23446d5014f7407d55ad477441847099cad24492b032335a0"
|
||||
|
||||
[[files]]
|
||||
file = "mods/ambiance-0.0.0-alpha.19.jar"
|
||||
hash = "9138adaaa0fb063100906e44453442d9e2596199769067207a2f7bd44f372756"
|
||||
file = "mods/ambiance-0.0.0-alpha.21.jar"
|
||||
hash = "c9dfd6ed13d1fdd2277e62d9bd2faa18c008d621bbcf8ef605736eefc3378663"
|
||||
|
||||
[[files]]
|
||||
file = "mods/anotherworld-0.0.0-alpha.55.jar"
|
||||
hash = "2d6250686739fd0bddcbff2d382e22fb9e403472926931f2879f6870af96ed64"
|
||||
hash = "0137f9a8109438c659c7a126ecde2e28982e063ee95f1991603a9ea81bbe7501"
|
||||
|
||||
[[files]]
|
||||
file = "mods/events-0.0.0-alpha.0.jar"
|
||||
hash = "4ac4ec54bf702a164443eb184796cca603cbad84607e794c2b24dbd5c7c221b9"
|
||||
hash = "3a666f7b7bdb9cbf7181eff3e49455768ac76905a482577990fdc1eb018e78d7"
|
||||
|
||||
[[files]]
|
||||
file = "mods/fabric-api.pw.toml"
|
||||
@@ -30,8 +30,8 @@ hash = "df032a6b051d0262cf24945c43e0e6b915e8cc1d62af62fe933932e7f35960c4"
|
||||
metafile = true
|
||||
|
||||
[[files]]
|
||||
file = "mods/iliketomoveit-0.0.0-alpha.15.jar"
|
||||
hash = "fe73255673eda5cbe16fe0bfd4a13951d9f103f58461ca84020e27cde408e569"
|
||||
file = "mods/iliketomoveit-0.0.0-alpha.16.jar"
|
||||
hash = "f42ed4fe37cbf3422e3b2493db562e82da3f2ba04568cea6ae304862e64e54df"
|
||||
|
||||
[[files]]
|
||||
file = "mods/iris.pw.toml"
|
||||
@@ -40,7 +40,7 @@ metafile = true
|
||||
|
||||
[[files]]
|
||||
file = "mods/itsalive-0.0.0-alpha.36.jar"
|
||||
hash = "49aab5f4b3c9145d3cc4e64ce46bff138e4c6147c83c985d402024920d929d0d"
|
||||
hash = "71c9d893fd0862610f203b854d1af19e0e6e4b2bc9e06f6da38d057e23a54ebd"
|
||||
|
||||
[[files]]
|
||||
file = "mods/jei.pw.toml"
|
||||
@@ -49,23 +49,23 @@ metafile = true
|
||||
|
||||
[[files]]
|
||||
file = "mods/masterkey-0.0.0-alpha.8.jar"
|
||||
hash = "9429a818c517b3943fdcbdd442800b9d854bf73c605df0f1ec761366574c129a"
|
||||
hash = "75ae764c2b86d2f4479f576d9a1cd8272c1979d754069277052ef11064fabbda"
|
||||
|
||||
[[files]]
|
||||
file = "mods/onlyfun-0.0.0-alpha.25.jar"
|
||||
hash = "005202d009ba00c5a3019aec6813cbdc2006d191299b2d1829051f73c2fb604a"
|
||||
hash = "69cca044dd3cd3fbbd6d9d45706a502ec17689c040521524eac3aa20ab93bf5f"
|
||||
|
||||
[[files]]
|
||||
file = "mods/ouch-0.0.0-alpha.10.jar"
|
||||
hash = "b4b5c5cf8164f6a0ce6131031fcbd0840c048a249d1b7c6e08f5b7aeed0e7656"
|
||||
hash = "c414a5b308796a797c6dce9b0337edfd06c536a18d1c746307f58e99e3a6be2c"
|
||||
|
||||
[[files]]
|
||||
file = "mods/redstoner-0.0.0-alpha.11.jar"
|
||||
hash = "457b4502ce2946963b4c2f21514a29c941f81df9bd1457f5db43fecdfa859a7e"
|
||||
hash = "753a7b4f8a26a836904099ed034dc36dcb371b87f5b67044940345fdadeb6b33"
|
||||
|
||||
[[files]]
|
||||
file = "mods/sanctuary-0.0.0-alpha.121.jar"
|
||||
hash = "ef2c827774c768289e034c9715d4f27c347b533f7476a6d355c7b45123fedcec"
|
||||
file = "mods/sanctuary-0.0.0-alpha.122.jar"
|
||||
hash = "b4ab04b167c50d412af791ccadf838ebcb0443303e05864c9940e02ec3cc0d40"
|
||||
|
||||
[[files]]
|
||||
file = "mods/simple-voice-chat.pw.toml"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
name = "Sanctuary 26.2"
|
||||
author = "KOKA99CAB"
|
||||
version = "26.2.0-alpha.217"
|
||||
version = "26.2.0-alpha.219"
|
||||
pack-format = "packwiz:1.1.0"
|
||||
|
||||
[index]
|
||||
file = "index.toml"
|
||||
hash-format = "sha256"
|
||||
hash = "176382d1bdb3797ba19d8d7acb093b9b49156f3b5b3270db803e59d24c6de7e1"
|
||||
hash = "a694c1327286dca4369aa64dfea7decbc36fedbba77188e7d8d310c08365d415"
|
||||
|
||||
[versions]
|
||||
fabric = "0.19.3"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"game": "minecraft",
|
||||
"name": "Sanctuary 26.2",
|
||||
"summary": "Sanctuary 26.2 — progression, exploration, worldgen and multiplayer systems by KOKA99CAB.",
|
||||
"versionId": "26.2.0-alpha.217",
|
||||
"versionId": "26.2.0-alpha.219",
|
||||
"files": [
|
||||
{
|
||||
"path": "mods/fabric-api-0.158.0+26.2.jar",
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"pack_version": "26.2.0-alpha.217",
|
||||
"pack_version": "26.2.0-alpha.219",
|
||||
"release_channel": "alpha",
|
||||
"minecraft_version": "26.2",
|
||||
"fabric_loader_version": "0.19.3",
|
||||
@@ -9,7 +9,7 @@
|
||||
"project_id": "FgOqyAXd",
|
||||
"project_slug": "sanctuary-koka99",
|
||||
"project_url": "https://modrinth.com/modpack/sanctuary-koka99",
|
||||
"primary_file": "sanctuary-26.2.0-alpha.217.mrpack",
|
||||
"primary_file": "sanctuary-26.2.0-alpha.219.mrpack",
|
||||
"shared_client_server_pack": true,
|
||||
"update_owner": "packwiz-installer",
|
||||
"check_on_launch": true,
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Dimension Alpha / Indev
|
||||
|
||||
`sanctuary:alpha` est la dimension historique finie de Sanctuary. Sanctuary
|
||||
possède son identifiant, son type de dimension et son générateur ; I Like To
|
||||
Move It possède exclusivement son portail et sa persistance.
|
||||
|
||||
## Contrat de génération
|
||||
|
||||
- volume historique exact : **128 × 128 × 64**, de X/Z `-64` à `63` et de
|
||||
Y `0` à `63` ;
|
||||
- terrain déterministe par seed : relief insulaire, plages, cavernes, minerais,
|
||||
eau, lave, végétation et maison de départ Indev ;
|
||||
- anneau extérieur en barrières, fond en bedrock et aucun placement au-delà de
|
||||
l'enveloppe finie ;
|
||||
- résidence et arrivée de portail calculées par l'API publique en lecture seule
|
||||
`SanctuaryAlphaWorld` ; l'arrivée est sèche, dégagée et séparée de la maison ;
|
||||
- la dimension est déclarée dans les profils Sanctuary et Overworld et reste
|
||||
disponible en solo comme sur serveur dédié.
|
||||
|
||||
Une même seed reconstruit le même volume, la même maison et les mêmes positions.
|
||||
L'ancien identifiant `portals:alpha` est migré vers `sanctuary:alpha` ; aucun
|
||||
nouvel identifiant persistant de Portals n'est repris.
|
||||
|
||||
## Accès
|
||||
|
||||
En jeu normal, construire un cadre extérieur de 4 × 5 en cobblestone moussue,
|
||||
laisser un intérieur vide de 2 × 3 et l'allumer au briquet. La première
|
||||
traversée crée une moitié distante à l'arrivée sûre ; les traversées suivantes
|
||||
réutilisent la paire persistée.
|
||||
|
||||
Au laboratoire, un opérateur peut vérifier le chargement de la dimension avec
|
||||
`/masterkey teleport @s sanctuary:alpha 0 48 0`. Cette commande téléporte aux
|
||||
coordonnées demandées sans recherche de surface : utiliser le portail pour
|
||||
l'arrivée sûre du gameplay normal.
|
||||
|
||||
Les textures historiques facultatives sont décrites dans
|
||||
[`ambiance/GOLDEN_DAYS.md`](../ambiance/GOLDEN_DAYS.md). Elles ne font pas
|
||||
partie de Sanctuary.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Third-party notices
|
||||
|
||||
## minecraft-python — Indev 20100223 level generator
|
||||
|
||||
The `AlphaIndevChunkFeature` terrain algorithm is adapted from the
|
||||
`minecraft-python` Indev 20100223 implementation by pythonengineer.
|
||||
|
||||
Source: https://github.com/pythonengineer/minecraft-python/tree/indev-20100223
|
||||
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2023 pythonengineer
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+77
-12
@@ -6,6 +6,12 @@ dependencies {
|
||||
implementation "maven.modrinth:u6dRKJwZ:VI3quY4l"
|
||||
}
|
||||
|
||||
tasks.named("jar") {
|
||||
from("THIRD_PARTY_NOTICES.md") {
|
||||
rename { "THIRD_PARTY_NOTICES_sanctuary.md" }
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("progressionModelSmoke", JavaExec) {
|
||||
group = "verification"
|
||||
description = "Round-trips the Sanctuary v3 statistic and unlock codec."
|
||||
@@ -86,6 +92,14 @@ tasks.register("capeJoinSyncSmoke", JavaExec) {
|
||||
mainClass = "fr.koka99cab.sanctuary26.sanctuary.gameplay.CapeJoinSyncQueueSmoke"
|
||||
}
|
||||
|
||||
tasks.register("alphaIndevGeneratorSmoke", JavaExec) {
|
||||
group = "verification"
|
||||
description = "Checks deterministic finite Indev islands, residences and safe portal arrivals."
|
||||
dependsOn tasks.named("testClasses")
|
||||
classpath = sourceSets.test.runtimeClasspath
|
||||
mainClass = "fr.koka99cab.sanctuary26.sanctuary.worldgen.feature.AlphaIndevGeneratorSmoke"
|
||||
}
|
||||
|
||||
tasks.register("verifyBlackMarket") {
|
||||
group = "verification"
|
||||
description = "Checks the physical sign market, flash Shop, escrow ledger and mailbox delivery."
|
||||
@@ -121,7 +135,7 @@ tasks.register("verifyBlackMarket") {
|
||||
def questData = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/QuestBoardData.java").text
|
||||
def quests = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/QuestBoardService.java").text
|
||||
def inventoryView = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/api/inventory/SanctuaryPlayerInventoryView.java").text
|
||||
if (project.version.toString() != "0.0.0-alpha.121"
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| !data.contains('SAVE_KEY = "black_market"') || !data.contains("DATA_VERSION = 2")
|
||||
|| !data.contains("ItemStack.CODEC.fieldOf(\"item\")") || !data.contains("replaceListing")
|
||||
|| !service.contains("LISTING_FEE_RUBIES = 1") || !service.contains("COMMISSION_PERCENT = 5")
|
||||
@@ -1602,8 +1616,8 @@ tasks.register("verifySanctuary") {
|
||||
|
||||
def worldgenRoot = file("src/main/resources/data/sanctuary/worldgen")
|
||||
def worldgenCounts = [
|
||||
density_function: 12, biome: 5, configured_feature: 12, configured_carver: 1,
|
||||
placed_feature: 18, noise_settings: 2, world_preset: 2
|
||||
density_function: 12, biome: 6, configured_feature: 13, configured_carver: 1,
|
||||
placed_feature: 19, noise_settings: 3, world_preset: 2
|
||||
]
|
||||
worldgenCounts.each { type, expected ->
|
||||
def actual = fileTree(new File(worldgenRoot, type.toString())).matching { include "**/*.json" }.files.size()
|
||||
@@ -2818,7 +2832,7 @@ tasks.register("verifyShopCurrencyRowsRelease") {
|
||||
"src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/BlackMarketService.java").text
|
||||
def shop = file(
|
||||
"src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopService.java").text
|
||||
if (project.version.toString() != "0.0.0-alpha.121"
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| migration.target?.modules?.sanctuary != "0.0.0-alpha.117"
|
||||
|| migration.shop_currency_inventory?.all_unlocked_rows_counted != true
|
||||
|| migration.shop_currency_inventory?.overflow_rows_counted != true
|
||||
@@ -2984,7 +2998,7 @@ tasks.register("verifyProgressivePauseMenu") {
|
||||
"pack/migrations/26.2.0-alpha.190-progressive-pause-menu-to-alpha.191.json"))
|
||||
def pauseMenu = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/PauseScreenMixin.java").text
|
||||
def costs = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/progression/SanctuaryProgressionCosts.java").text
|
||||
if (project.version.toString() != "0.0.0-alpha.121"
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.191"
|
||||
|| migration.target?.modules?.sanctuary != "0.0.0-alpha.109"
|
||||
|| migration.pause_menu?.progression_full_width != true
|
||||
@@ -3022,7 +3036,7 @@ tasks.register("verifyShopPricingLayout") {
|
||||
"pack/migrations/26.2.0-alpha.192-shop-pricing-layout-to-alpha.193.json"))
|
||||
def screen = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryShopScreen.java").text
|
||||
def progression = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopProgression.java").text
|
||||
if (project.version.toString() != "0.0.0-alpha.121"
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| migration.target?.modules?.sanctuary != "0.0.0-alpha.110"
|
||||
|| migration.shop_layout?.locked_offer_buttons != 6
|
||||
|| migration.shop_layout?.button_slots != [4, 5, 6, 7, 8, 9]
|
||||
@@ -3053,7 +3067,7 @@ tasks.register("verifyShopCsvBossGates") {
|
||||
"pack/migrations/26.2.0-alpha.194-shop-csv-boss-gates-to-alpha.195.json"))
|
||||
def provider = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopCatalogProvider.java").text
|
||||
def catalog = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopOfferCatalog.java").text
|
||||
if (project.version.toString() != "0.0.0-alpha.121"
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.195"
|
||||
|| migration.target?.modules?.sanctuary != "0.0.0-alpha.111"
|
||||
|| migration.compatibility?.sanctuary_data_version != 11
|
||||
@@ -3084,7 +3098,7 @@ tasks.register("verifyDeliveryBoxOrientation") {
|
||||
def blockstate = new JsonSlurper().parse(
|
||||
file("src/main/resources/assets/sanctuary/blockstates/delivery_box.json"))
|
||||
def expectedVariants = ["facing=north", "facing=east", "facing=south", "facing=west"].toSet()
|
||||
if (project.version.toString() != "0.0.0-alpha.121"
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| migration.target?.modules?.sanctuary != "0.0.0-alpha.112"
|
||||
|| migration.mailbox?.id != "sanctuary:delivery_box"
|
||||
|| migration.mailbox?.horizontal_facing != true
|
||||
@@ -3112,7 +3126,7 @@ tasks.register("verifyInventoryShiftClick") {
|
||||
def mixin = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/AbstractContainerMenuMixin.java").text
|
||||
def screen = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AbstractContainerScreenMixin.java").text
|
||||
def gui = file("INVENTORY_GUI.md").text
|
||||
if (project.version.toString() != "0.0.0-alpha.121"
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| !transfer.contains("shouldAppendOverflow")
|
||||
|| !transfer.contains("isVanillaStorageRange")
|
||||
|| !transfer.contains("hotbarStart")
|
||||
@@ -3158,7 +3172,7 @@ tasks.register("verifyQuestRequests") {
|
||||
new JsonSlurper().parse(file("src/main/resources/data/sanctuary/loot_table/blocks/${path}.json"))
|
||||
.pools[0].entries[0].name
|
||||
}
|
||||
if (project.version.toString() != "0.0.0-alpha.121"
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| migration.target?.modules?.sanctuary != "0.0.0-alpha.113"
|
||||
|| migration.quest_requests?.save_key != "quest_requests"
|
||||
|| migration.quest_requests?.data_version != 1
|
||||
@@ -3216,7 +3230,7 @@ tasks.register("verifyQuestRequestContracts") {
|
||||
def locales = ["fr_fr", "en_us", "ru_ru"].collectEntries { locale ->
|
||||
[(locale): new JsonSlurper().parse(file("src/main/resources/assets/sanctuary/lang/${locale}.json"))]
|
||||
}
|
||||
if (project.version.toString() != "0.0.0-alpha.121"
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.198"
|
||||
|| migration.source?.modules?.sanctuary != "0.0.0-alpha.114"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.199"
|
||||
@@ -3285,7 +3299,7 @@ tasks.register("verifyQuestRequestEscrow") {
|
||||
def locales = ["fr_fr", "en_us", "ru_ru"].collectEntries { locale ->
|
||||
[(locale): new JsonSlurper().parse(file("src/main/resources/assets/sanctuary/lang/${locale}.json"))]
|
||||
}
|
||||
if (project.version.toString() != "0.0.0-alpha.121"
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| migration.source?.pack_version != "26.2.0-alpha.200"
|
||||
|| migration.source?.modules?.sanctuary != "0.0.0-alpha.115"
|
||||
|| migration.target?.pack_version != "26.2.0-alpha.201"
|
||||
@@ -3330,6 +3344,55 @@ tasks.named("verifySanctuary") {
|
||||
dependsOn tasks.named("verifyInventoryShiftClick")
|
||||
}
|
||||
|
||||
tasks.register("verifyAlphaIndev") {
|
||||
group = "verification"
|
||||
description = "Checks the alpha.122 finite Indev world, migration and attribution contract."
|
||||
inputs.file(file("ALPHA.md"))
|
||||
inputs.file(file("THIRD_PARTY_NOTICES.md"))
|
||||
inputs.file(file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/api/world/SanctuaryAlphaWorld.java"))
|
||||
inputs.file(file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/worldgen/feature/AlphaIndevChunkFeature.java"))
|
||||
inputs.files(fileTree("src/main/resources/data/sanctuary") { include "**/alpha*.json" })
|
||||
inputs.files(fileTree("src/main/resources/assets/sanctuary/lang") { include "*.json" })
|
||||
inputs.file(rootProject.file("pack/migrations/26.2.0-alpha.218-alpha-indev-to-alpha.219.json"))
|
||||
doLast {
|
||||
def migration = new JsonSlurper().parse(rootProject.file(
|
||||
"pack/migrations/26.2.0-alpha.218-alpha-indev-to-alpha.219.json"))
|
||||
def presetFiles = ["sanctuary", "overworld"].collect {
|
||||
new JsonSlurper().parse(file("src/main/resources/data/sanctuary/worldgen/world_preset/${it}.json"))
|
||||
}
|
||||
def dimensionType = new JsonSlurper().parse(file(
|
||||
"src/main/resources/data/sanctuary/dimension_type/alpha.json"))
|
||||
def configured = new JsonSlurper().parse(file(
|
||||
"src/main/resources/data/sanctuary/worldgen/configured_feature/alpha_indev_chunk.json"))
|
||||
def javaText = [
|
||||
file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/api/world/SanctuaryAlphaWorld.java"),
|
||||
file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/worldgen/feature/AlphaIndevChunkFeature.java")
|
||||
]*.text.join("\n")
|
||||
def locales = ["fr_fr", "en_us", "ru_ru"].collect {
|
||||
new JsonSlurper().parse(file("src/main/resources/assets/sanctuary/lang/${it}.json"))
|
||||
}
|
||||
if (project.version.toString() != "0.0.0-alpha.122"
|
||||
|| migration.target?.modules?.sanctuary != "0.0.0-alpha.122"
|
||||
|| migration.alpha_world?.dimension != "sanctuary:alpha"
|
||||
|| migration.alpha_world?.legacy_dimension != "portals:alpha"
|
||||
|| migration.alpha_world?.width != 128 || migration.alpha_world?.depth != 128
|
||||
|| migration.alpha_world?.height != 64 || migration.alpha_world?.deterministic_per_seed != true
|
||||
|| migration.alpha_world?.finite_barrier_boundary != true
|
||||
|| presetFiles.any { it.dimensions?.get("sanctuary:alpha") == null }
|
||||
|| dimensionType.min_y != 0 || dimensionType.height != 64 || dimensionType.logical_height != 64
|
||||
|| configured.type != "sanctuary:alpha_indev_chunk"
|
||||
|| !javaText.contains("public static final int WIDTH = 128")
|
||||
|| !javaText.contains("public static final int HEIGHT = 64")
|
||||
|| !javaText.contains("Blocks.BARRIER.defaultBlockState()")
|
||||
|| !javaText.contains("Blocks.BEDROCK.defaultBlockState()")
|
||||
|| !javaText.contains("public static BlockPos portalArrival(long seed)")
|
||||
|| locales.any { !it.containsKey("dimension.sanctuary.alpha") }
|
||||
|| !file("THIRD_PARTY_NOTICES.md").text.contains("BSD 3-Clause License")) {
|
||||
throw new GradleException("Sanctuary alpha.122 finite Indev contract is incomplete")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("check") {
|
||||
dependsOn tasks.named("verifySanctuary")
|
||||
dependsOn tasks.named("verifyDeliveryBoxOrientation")
|
||||
@@ -3339,4 +3402,6 @@ tasks.named("check") {
|
||||
dependsOn tasks.named("verifyShopCurrencyRowsRelease")
|
||||
dependsOn tasks.named("celestialGraphSmoke")
|
||||
dependsOn tasks.named("questRequestModelSmoke")
|
||||
dependsOn tasks.named("alphaIndevGeneratorSmoke")
|
||||
dependsOn tasks.named("verifyAlphaIndev")
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package fr.koka99cab.sanctuary26.sanctuary.api.world;
|
||||
|
||||
import fr.koka99cab.sanctuary26.sanctuary.worldgen.feature.AlphaIndevChunkFeature;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
/** Public, read-only geometry contract for the finite {@code sanctuary:alpha} world. */
|
||||
public final class SanctuaryAlphaWorld {
|
||||
public static final int WIDTH = AlphaIndevChunkFeature.WIDTH;
|
||||
public static final int DEPTH = AlphaIndevChunkFeature.DEPTH;
|
||||
public static final int HEIGHT = AlphaIndevChunkFeature.HEIGHT;
|
||||
|
||||
private SanctuaryAlphaWorld() {
|
||||
}
|
||||
|
||||
/** Historical residence position inside the deterministic Indev starting house. */
|
||||
public static BlockPos residence(long seed) {
|
||||
return AlphaIndevChunkFeature.notchHome(seed);
|
||||
}
|
||||
|
||||
/** Safe portal feet position outside the house for this world's seed. */
|
||||
public static BlockPos portalArrival(long seed) {
|
||||
return AlphaIndevChunkFeature.portalArrival(seed);
|
||||
}
|
||||
|
||||
public static boolean containsHorizontal(BlockPos pos) {
|
||||
return pos.getX() >= AlphaIndevChunkFeature.MIN_X && pos.getX() <= AlphaIndevChunkFeature.MAX_X
|
||||
&& pos.getZ() >= AlphaIndevChunkFeature.MIN_Z && pos.getZ() <= AlphaIndevChunkFeature.MAX_Z;
|
||||
}
|
||||
}
|
||||
+5
@@ -2,6 +2,7 @@ package fr.koka99cab.sanctuary26.sanctuary.worldgen;
|
||||
|
||||
import fr.koka99cab.sanctuary26.sanctuary.SanctuaryMod;
|
||||
import fr.koka99cab.sanctuary26.sanctuary.worldgen.feature.MatterDepthMaterializationFeature;
|
||||
import fr.koka99cab.sanctuary26.sanctuary.worldgen.feature.AlphaIndevChunkFeature;
|
||||
import fr.koka99cab.sanctuary26.sanctuary.worldgen.feature.SanctuaryWaterLakeFeature;
|
||||
import fr.koka99cab.sanctuary26.sanctuary.worldgen.feature.SulfurCaveGeologyFeature;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
|
||||
@@ -21,6 +22,9 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
|
||||
/** Registers the two generator-specific features migrated from Sanctuary 26.1.2. */
|
||||
public final class SanctuaryFeatures {
|
||||
public static final Identifier ALPHA_INDEV_CHUNK_ID = SanctuaryMod.id("alpha_indev_chunk");
|
||||
public static final Feature<NoneFeatureConfiguration> ALPHA_INDEV_CHUNK =
|
||||
new AlphaIndevChunkFeature(NoneFeatureConfiguration.CODEC);
|
||||
public static final Identifier MATTER_DEPTH_MATERIALIZATION_ID =
|
||||
SanctuaryMod.id("matter_depth_materialization");
|
||||
public static final ResourceKey<PlacedFeature> MATTER_DEPTH_MATERIALIZATION_PLACED_FEATURE =
|
||||
@@ -52,6 +56,7 @@ public final class SanctuaryFeatures {
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
Registry.register(BuiltInRegistries.FEATURE, ALPHA_INDEV_CHUNK_ID, ALPHA_INDEV_CHUNK);
|
||||
Registry.register(BuiltInRegistries.FEATURE,
|
||||
MATTER_DEPTH_MATERIALIZATION_ID, MATTER_DEPTH_MATERIALIZATION);
|
||||
Registry.register(BuiltInRegistries.FEATURE, WATER_LAKE_ID, WATER_LAKE);
|
||||
|
||||
+857
@@ -0,0 +1,857 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 KOKA99CAB
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* The terrain algorithm is a Java adaptation of the BSD-3-Clause
|
||||
* minecraft-python Indev 20100223 LevelGenerator by pythonengineer.
|
||||
* See Sanctuary's bundled THIRD_PARTY_NOTICES.md.
|
||||
*/
|
||||
|
||||
package fr.koka99cab.sanctuary26.sanctuary.worldgen.feature;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.LeavesBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
|
||||
/** Generates the finite 128x128x64 normal Island preset from Minecraft Indev. */
|
||||
public final class AlphaIndevChunkFeature extends Feature<NoneFeatureConfiguration> {
|
||||
public static final int WIDTH = 128;
|
||||
public static final int DEPTH = 128;
|
||||
public static final int HEIGHT = 64;
|
||||
public static final int MIN_X = -WIDTH / 2;
|
||||
public static final int MIN_Z = -DEPTH / 2;
|
||||
public static final int MAX_X = MIN_X + WIDTH - 1;
|
||||
public static final int MAX_Z = MIN_Z + DEPTH - 1;
|
||||
public static final int WATER_LEVEL = HEIGHT - 32;
|
||||
private static final int CHUNK_SIZE = 16;
|
||||
private static final int MAX_CACHED_ISLANDS = 4;
|
||||
private static final Map<Long, IndevIsland> CACHE = Collections.synchronizedMap(
|
||||
new LinkedHashMap<>(MAX_CACHED_ISLANDS + 1, 0.75F, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<Long, IndevIsland> eldest) {
|
||||
return size() > MAX_CACHED_ISLANDS;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
private static final byte AIR = 0;
|
||||
private static final byte STONE = 1;
|
||||
private static final byte GRASS = 2;
|
||||
private static final byte DIRT = 3;
|
||||
private static final byte WATER = 4;
|
||||
private static final byte LAVA = 5;
|
||||
private static final byte SAND = 6;
|
||||
private static final byte GRAVEL = 7;
|
||||
private static final byte COAL_ORE = 8;
|
||||
private static final byte IRON_ORE = 9;
|
||||
private static final byte GOLD_ORE = 10;
|
||||
private static final byte DIAMOND_ORE = 11;
|
||||
private static final byte OAK_LOG = 12;
|
||||
private static final byte OAK_LEAVES = 13;
|
||||
private static final byte DANDELION = 14;
|
||||
private static final byte POPPY = 15;
|
||||
private static final byte BROWN_MUSHROOM = 16;
|
||||
private static final byte RED_MUSHROOM = 17;
|
||||
private static final byte OBSIDIAN = 18;
|
||||
private static final byte OAK_PLANKS = 19;
|
||||
private static final byte TORCH = 20;
|
||||
private static final byte MARKER = (byte) 0xFF;
|
||||
|
||||
private static final BlockState PERSISTENT_OAK_LEAVES = Blocks.OAK_LEAVES.defaultBlockState()
|
||||
.setValue(LeavesBlock.PERSISTENT, true);
|
||||
|
||||
public AlphaIndevChunkFeature(Codec<NoneFeatureConfiguration> codec) {
|
||||
super(codec);
|
||||
}
|
||||
|
||||
/** Returns the block where the resident stands inside the deterministic Indev house. */
|
||||
public static BlockPos notchHome(long seed) {
|
||||
return island(seed).notchHome();
|
||||
}
|
||||
|
||||
/** Returns a safe surface position outside the deterministic Indev house. */
|
||||
public static BlockPos portalArrival(long seed) {
|
||||
return island(seed).portalArrival();
|
||||
}
|
||||
|
||||
/** Stable test fingerprint covering terrain, decorations, house and portal arrival. */
|
||||
static long fingerprint(long seed) {
|
||||
return island(seed).fingerprint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
|
||||
WorldGenLevel level = context.level();
|
||||
BlockPos origin = context.origin();
|
||||
int chunkX = Math.floorDiv(origin.getX(), CHUNK_SIZE) * CHUNK_SIZE;
|
||||
int chunkZ = Math.floorDiv(origin.getZ(), CHUNK_SIZE) * CHUNK_SIZE;
|
||||
int startX = Math.max(chunkX, MIN_X);
|
||||
int endX = Math.min(chunkX + CHUNK_SIZE - 1, MAX_X);
|
||||
int startZ = Math.max(chunkZ, MIN_Z);
|
||||
int endZ = Math.min(chunkZ + CHUNK_SIZE - 1, MAX_Z);
|
||||
|
||||
if (startX > endX || startZ > endZ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IndevIsland island = island(level.getSeed());
|
||||
BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos();
|
||||
boolean placed = false;
|
||||
|
||||
for (int worldX = startX; worldX <= endX; worldX++) {
|
||||
int localX = worldX - MIN_X;
|
||||
for (int worldZ = startZ; worldZ <= endZ; worldZ++) {
|
||||
int localZ = worldZ - MIN_Z;
|
||||
boolean boundary = localX == 0 || localX == WIDTH - 1 || localZ == 0 || localZ == DEPTH - 1;
|
||||
|
||||
for (int y = 0; y < HEIGHT; y++) {
|
||||
byte block = island.get(localX, y, localZ);
|
||||
BlockState state;
|
||||
|
||||
if (boundary) {
|
||||
state = Blocks.BARRIER.defaultBlockState();
|
||||
} else if (y == 0) {
|
||||
state = Blocks.BEDROCK.defaultBlockState();
|
||||
} else if (block == AIR) {
|
||||
continue;
|
||||
} else {
|
||||
state = stateFor(block);
|
||||
}
|
||||
|
||||
cursor.set(worldX, y, worldZ);
|
||||
placed |= level.setBlock(cursor, state, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return placed;
|
||||
}
|
||||
|
||||
private static IndevIsland island(long seed) {
|
||||
synchronized (CACHE) {
|
||||
return CACHE.computeIfAbsent(seed, IndevIsland::new);
|
||||
}
|
||||
}
|
||||
|
||||
private static BlockState stateFor(byte block) {
|
||||
return switch (block) {
|
||||
case STONE -> Blocks.STONE.defaultBlockState();
|
||||
case GRASS -> Blocks.GRASS_BLOCK.defaultBlockState();
|
||||
case DIRT -> Blocks.DIRT.defaultBlockState();
|
||||
case WATER -> Blocks.WATER.defaultBlockState();
|
||||
case LAVA -> Blocks.LAVA.defaultBlockState();
|
||||
case SAND -> Blocks.SAND.defaultBlockState();
|
||||
case GRAVEL -> Blocks.GRAVEL.defaultBlockState();
|
||||
case COAL_ORE -> Blocks.COAL_ORE.defaultBlockState();
|
||||
case IRON_ORE -> Blocks.IRON_ORE.defaultBlockState();
|
||||
case GOLD_ORE -> Blocks.GOLD_ORE.defaultBlockState();
|
||||
case DIAMOND_ORE -> Blocks.DIAMOND_ORE.defaultBlockState();
|
||||
case OAK_LOG -> Blocks.OAK_LOG.defaultBlockState();
|
||||
case OAK_LEAVES -> PERSISTENT_OAK_LEAVES;
|
||||
case DANDELION -> Blocks.DANDELION.defaultBlockState();
|
||||
case POPPY -> Blocks.POPPY.defaultBlockState();
|
||||
case BROWN_MUSHROOM -> Blocks.BROWN_MUSHROOM.defaultBlockState();
|
||||
case RED_MUSHROOM -> Blocks.RED_MUSHROOM.defaultBlockState();
|
||||
case OBSIDIAN -> Blocks.OBSIDIAN.defaultBlockState();
|
||||
case OAK_PLANKS -> Blocks.OAK_PLANKS.defaultBlockState();
|
||||
case TORCH -> Blocks.TORCH.defaultBlockState();
|
||||
default -> Blocks.AIR.defaultBlockState();
|
||||
};
|
||||
}
|
||||
|
||||
private static final class IndevIsland {
|
||||
private final byte[] blocks = new byte[WIDTH * DEPTH * HEIGHT];
|
||||
private final int[] floodQueue = new int[blocks.length];
|
||||
private final int[] spawn;
|
||||
private final BlockPos portalArrival;
|
||||
|
||||
private IndevIsland(long seed) {
|
||||
Random random = new Random(seed);
|
||||
int[] heightMap = raiseTerrain(random);
|
||||
erodeTerrain(random, heightMap);
|
||||
soilTerrain(random, heightMap);
|
||||
growBeaches(random, heightMap);
|
||||
carveCaves(random);
|
||||
populateOre(random, COAL_ORE, 1000, 10, (HEIGHT << 2) / 5);
|
||||
populateOre(random, IRON_ORE, 800, 8, HEIGHT * 3 / 5);
|
||||
populateOre(random, GOLD_ORE, 500, 6, (HEIGHT << 1) / 5);
|
||||
populateOre(random, DIAMOND_ORE, 800, 4, HEIGHT / 5);
|
||||
meltLava(random);
|
||||
waterIsland(random);
|
||||
this.spawn = findSpawn(seed);
|
||||
generateSpawnHouse(this.spawn[0], this.spawn[1], this.spawn[2]);
|
||||
growGrass();
|
||||
growTrees(random);
|
||||
populatePlants(random, DANDELION, 100);
|
||||
populatePlants(random, POPPY, 100);
|
||||
populatePlants(random, BROWN_MUSHROOM, 50);
|
||||
populatePlants(random, RED_MUSHROOM, 50);
|
||||
this.portalArrival = findPortalArrival();
|
||||
}
|
||||
|
||||
private byte get(int x, int y, int z) {
|
||||
if (!inside(x, y, z)) {
|
||||
return AIR;
|
||||
}
|
||||
return blocks[index(x, y, z)];
|
||||
}
|
||||
|
||||
private BlockPos notchHome() {
|
||||
return new BlockPos(this.spawn[0] + MIN_X, this.spawn[1] - 1, this.spawn[2] + MIN_Z);
|
||||
}
|
||||
|
||||
private BlockPos portalArrival() {
|
||||
return portalArrival;
|
||||
}
|
||||
|
||||
private long fingerprint() {
|
||||
long hash = 0xcbf29ce484222325L;
|
||||
for (byte block : blocks) {
|
||||
hash ^= Byte.toUnsignedLong(block);
|
||||
hash *= 0x100000001b3L;
|
||||
}
|
||||
hash ^= notchHome().asLong();
|
||||
hash *= 0x100000001b3L;
|
||||
hash ^= portalArrival.asLong();
|
||||
return hash;
|
||||
}
|
||||
|
||||
private void set(int x, int y, int z, byte block) {
|
||||
if (inside(x, y, z)) {
|
||||
blocks[index(x, y, z)] = block;
|
||||
}
|
||||
}
|
||||
|
||||
private int[] raiseTerrain(Random random) {
|
||||
int[] heightMap = new int[WIDTH * DEPTH];
|
||||
Distort raiseOne = new Distort(new Octaves(random, 8), new Octaves(random, 8));
|
||||
Distort raiseTwo = new Distort(new Octaves(random, 8), new Octaves(random, 8));
|
||||
Octaves selector = new Octaves(random, 6);
|
||||
Octaves islandNoise = new Octaves(random, 2);
|
||||
|
||||
for (int x = 0; x < WIDTH; x++) {
|
||||
double normalizedX = Math.abs((x / (WIDTH - 1.0D) - 0.5D) * 2.0D);
|
||||
for (int z = 0; z < DEPTH; z++) {
|
||||
double normalizedZ = Math.abs((z / (DEPTH - 1.0D) - 0.5D) * 2.0D);
|
||||
double first = raiseOne.noise(x * 1.3D, z * 1.3D) / 6.0D - 4.0D;
|
||||
double second = raiseTwo.noise(x * 1.3D, z * 1.3D) / 5.0D + 6.0D;
|
||||
|
||||
if (selector.noise(x, z) / 8.0D > 0.0D) {
|
||||
second = first;
|
||||
}
|
||||
|
||||
double highest = Math.max(first, second) / 2.0D;
|
||||
double islandDistance = Math.sqrt(normalizedX * normalizedX + normalizedZ * normalizedZ) * 1.2D;
|
||||
double islandShape = islandNoise.noise(x * 0.05D, z * 0.05D) / 4.0D + 1.0D;
|
||||
islandDistance = Math.min(islandDistance, islandShape);
|
||||
islandDistance = Math.max(islandDistance, Math.max(normalizedX, normalizedZ));
|
||||
islandDistance = Math.max(0.0D, Math.min(1.0D, islandDistance));
|
||||
islandDistance *= islandDistance;
|
||||
highest = highest * (1.0D - islandDistance) - islandDistance * 10.0D + 5.0D;
|
||||
|
||||
if (highest < 0.0D) {
|
||||
highest -= highest * highest * 0.2D;
|
||||
}
|
||||
|
||||
heightMap[x + z * WIDTH] = (int) highest;
|
||||
}
|
||||
}
|
||||
|
||||
return heightMap;
|
||||
}
|
||||
|
||||
private void erodeTerrain(Random random, int[] heightMap) {
|
||||
Distort erosion = new Distort(new Octaves(random, 8), new Octaves(random, 8));
|
||||
Distort erosionSelector = new Distort(new Octaves(random, 8), new Octaves(random, 8));
|
||||
|
||||
for (int x = 0; x < WIDTH; x++) {
|
||||
for (int z = 0; z < DEPTH; z++) {
|
||||
double noise = erosion.noise(x << 1, z << 1) / 8.0D;
|
||||
int offset = erosionSelector.noise(x << 1, z << 1) > 0.0D ? 1 : 0;
|
||||
|
||||
if (noise > 2.0D) {
|
||||
int height = heightMap[x + z * WIDTH];
|
||||
heightMap[x + z * WIDTH] = ((height - offset) / 2 << 1) + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void soilTerrain(Random random, int[] heightMap) {
|
||||
Octaves soilNoise = new Octaves(random, 8);
|
||||
Octaves floatingNoise = new Octaves(random, 8);
|
||||
|
||||
for (int x = 0; x < WIDTH; x++) {
|
||||
double normalizedX = Math.abs((x / (WIDTH - 1.0D) - 0.5D) * 2.0D);
|
||||
for (int z = 0; z < DEPTH; z++) {
|
||||
double normalizedZ = Math.abs((z / (DEPTH - 1.0D) - 0.5D) * 2.0D);
|
||||
double floatingDistance = Math.max(normalizedX, normalizedZ);
|
||||
floatingDistance *= floatingDistance * floatingDistance;
|
||||
int dirtLevel = heightMap[x + z * WIDTH] + WATER_LEVEL;
|
||||
int stoneLevel = dirtLevel + (int) (soilNoise.noise(x, z) / 24.0D) - 4;
|
||||
heightMap[x + z * WIDTH] = Math.max(dirtLevel, stoneLevel);
|
||||
heightMap[x + z * WIDTH] = Math.max(1, Math.min(HEIGHT - 2, heightMap[x + z * WIDTH]));
|
||||
|
||||
// Consumed by the original generator even for a non-floating map.
|
||||
double floatingValue = floatingNoise.noise(x * 2.3D, z * 2.3D) / 24.0D;
|
||||
double unusedFloatingHeight = Math.copySign(Math.sqrt(Math.abs(floatingValue)), floatingValue) * 20.0D + WATER_LEVEL;
|
||||
if (unusedFloatingHeight * (1.0D - floatingDistance) + floatingDistance * HEIGHT > WATER_LEVEL) {
|
||||
// Deliberately empty: this preserves the historical noise calls and arithmetic.
|
||||
}
|
||||
|
||||
for (int y = 0; y < HEIGHT; y++) {
|
||||
byte block = AIR;
|
||||
if (y <= dirtLevel) {
|
||||
block = DIRT;
|
||||
}
|
||||
if (y <= stoneLevel) {
|
||||
block = STONE;
|
||||
}
|
||||
set(x, y, z, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void growBeaches(Random random, int[] heightMap) {
|
||||
Octaves sandNoise = new Octaves(random, 8);
|
||||
Octaves gravelNoise = new Octaves(random, 8);
|
||||
int beachLevel = WATER_LEVEL - 1;
|
||||
|
||||
for (int x = 0; x < WIDTH; x++) {
|
||||
for (int z = 0; z < DEPTH; z++) {
|
||||
boolean beach = sandNoise.noise(x, z) > -8.0D;
|
||||
boolean gravel = gravelNoise.noise(x, z) > 12.0D;
|
||||
int top = heightMap[x + z * WIDTH];
|
||||
byte above = get(x, top + 1, z);
|
||||
|
||||
if ((above == WATER || above == AIR) && top <= WATER_LEVEL - 1 && gravel) {
|
||||
set(x, top, z, GRAVEL);
|
||||
}
|
||||
|
||||
if (above == AIR && top <= beachLevel && beach && get(x, top, z) != AIR) {
|
||||
set(x, top, z, SAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void carveCaves(Random random) {
|
||||
int caveCount = WIDTH * HEIGHT * DEPTH / 256 / 64 << 1;
|
||||
|
||||
for (int cave = 0; cave < caveCount; cave++) {
|
||||
float x = random.nextFloat() * WIDTH;
|
||||
float y = random.nextFloat() * HEIGHT;
|
||||
float z = random.nextFloat() * DEPTH;
|
||||
int length = (int) ((random.nextFloat() + random.nextFloat()) * 200.0F);
|
||||
float horizontal = random.nextFloat() * (float) Math.PI * 2.0F;
|
||||
float horizontalVelocity = 0.0F;
|
||||
float vertical = random.nextFloat() * (float) Math.PI * 2.0F;
|
||||
float verticalVelocity = 0.0F;
|
||||
float thickness = random.nextFloat() * random.nextFloat();
|
||||
|
||||
for (int step = 0; step < length; step++) {
|
||||
x += Math.sin(horizontal) * Math.cos(vertical);
|
||||
z += Math.cos(horizontal) * Math.cos(vertical);
|
||||
y += Math.sin(vertical);
|
||||
horizontal += horizontalVelocity * 0.2F;
|
||||
horizontalVelocity *= 0.9F;
|
||||
horizontalVelocity += random.nextFloat() - random.nextFloat();
|
||||
vertical += verticalVelocity * 0.5F;
|
||||
vertical *= 0.5F;
|
||||
verticalVelocity *= 12.0F / 16.0F;
|
||||
verticalVelocity += random.nextFloat() - random.nextFloat();
|
||||
|
||||
if (random.nextFloat() < 0.25F || length == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float disturbedX = x + (random.nextFloat() * 4.0F - 2.0F) * 0.2F;
|
||||
float disturbedY = y + (random.nextFloat() * 4.0F - 2.0F) * 0.2F;
|
||||
float disturbedZ = z + (random.nextFloat() * 4.0F - 2.0F) * 0.2F;
|
||||
float depthScale = (HEIGHT - disturbedY) / HEIGHT;
|
||||
float radius = 1.2F + (depthScale * 3.5F + 1.0F) * thickness;
|
||||
radius = (float) Math.sin(step * Math.PI / length) * radius;
|
||||
|
||||
for (int blockX = (int) (disturbedX - radius); blockX <= (int) (disturbedX + radius); blockX++) {
|
||||
for (int blockY = (int) (disturbedY - radius); blockY <= (int) (disturbedY + radius); blockY++) {
|
||||
for (int blockZ = (int) (disturbedZ - radius); blockZ <= (int) (disturbedZ + radius); blockZ++) {
|
||||
double dx = blockX - disturbedX;
|
||||
double dy = blockY - disturbedY;
|
||||
double dz = blockZ - disturbedZ;
|
||||
if (dx * dx + dy * dy * 2.0D + dz * dz < radius * radius
|
||||
&& blockX > 0 && blockY > 0 && blockZ > 0
|
||||
&& blockX < WIDTH - 1 && blockY < HEIGHT - 1 && blockZ < DEPTH - 1
|
||||
&& get(blockX, blockY, blockZ) == STONE) {
|
||||
set(blockX, blockY, blockZ, AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void populateOre(Random random, byte ore, int frequency, int volume, int maxHeight) {
|
||||
int veinCount = WIDTH * DEPTH * HEIGHT / 256 / 64 * frequency / 100;
|
||||
|
||||
for (int vein = 0; vein < veinCount; vein++) {
|
||||
float x = random.nextFloat() * WIDTH;
|
||||
float y = random.nextFloat() * HEIGHT;
|
||||
float z = random.nextFloat() * DEPTH;
|
||||
|
||||
if (y > maxHeight) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int steps = (int) ((random.nextFloat() + random.nextFloat()) * 75.0F * volume / 100.0F);
|
||||
float horizontal = random.nextFloat() * (float) Math.PI * 2.0F;
|
||||
float horizontalVelocity = 0.0F;
|
||||
float vertical = random.nextFloat() * (float) Math.PI * 2.0F;
|
||||
float verticalVelocity = 0.0F;
|
||||
|
||||
for (int step = 0; step < steps; step++) {
|
||||
x += Math.sin(horizontal) * Math.cos(vertical);
|
||||
z += Math.cos(horizontal) * Math.cos(vertical);
|
||||
y += Math.sin(vertical);
|
||||
horizontal += horizontalVelocity * 0.2F;
|
||||
horizontalVelocity *= 0.9F;
|
||||
horizontalVelocity = random.nextFloat() - random.nextFloat();
|
||||
vertical = (vertical + verticalVelocity * 0.5F) * 0.5F;
|
||||
verticalVelocity = verticalVelocity * 0.9F + random.nextFloat() - random.nextFloat();
|
||||
float radius = (float) Math.sin(step * Math.PI / steps) * volume / 100.0F + 1.0F;
|
||||
|
||||
for (int blockX = (int) (x - radius); blockX <= (int) (x + radius); blockX++) {
|
||||
for (int blockY = (int) (y - radius); blockY <= (int) (y + radius); blockY++) {
|
||||
for (int blockZ = (int) (z - radius); blockZ <= (int) (z + radius); blockZ++) {
|
||||
double dx = blockX - x;
|
||||
double dy = blockY - y;
|
||||
double dz = blockZ - z;
|
||||
if (dx * dx + dy * dy * 2.0D + dz * dz < radius * radius
|
||||
&& blockX >= 1 && blockY >= 1 && blockZ >= 1
|
||||
&& blockX < WIDTH - 1 && blockY < HEIGHT - 1 && blockZ < DEPTH - 1
|
||||
&& get(blockX, blockY, blockZ) == STONE) {
|
||||
set(blockX, blockY, blockZ, ore);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void meltLava(Random random) {
|
||||
int attempts = WIDTH * DEPTH * HEIGHT / 2000;
|
||||
int groundLevel = WATER_LEVEL - 2;
|
||||
|
||||
for (int attempt = 0; attempt < attempts; attempt++) {
|
||||
int x = random.nextInt(WIDTH);
|
||||
int y = Math.min(Math.min(random.nextInt(groundLevel), random.nextInt(groundLevel)),
|
||||
Math.min(random.nextInt(groundLevel), random.nextInt(groundLevel)));
|
||||
int z = random.nextInt(DEPTH);
|
||||
|
||||
if (get(x, y, z) != AIR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int filled = floodFill(x, y, z, AIR, MARKER);
|
||||
if (filled > 0 && filled < 640) {
|
||||
floodFill(x, y, z, MARKER, LAVA);
|
||||
} else {
|
||||
floodFill(x, y, z, MARKER, AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void waterIsland(Random random) {
|
||||
for (int x = 0; x < WIDTH; x++) {
|
||||
floodFill(x, WATER_LEVEL - 1, 0, AIR, WATER);
|
||||
floodFill(x, WATER_LEVEL - 1, DEPTH - 1, AIR, WATER);
|
||||
}
|
||||
for (int z = 0; z < DEPTH; z++) {
|
||||
floodFill(WIDTH - 1, WATER_LEVEL - 1, z, AIR, WATER);
|
||||
floodFill(0, WATER_LEVEL - 1, z, AIR, WATER);
|
||||
}
|
||||
|
||||
int attempts = WIDTH * DEPTH * HEIGHT / 1000;
|
||||
for (int attempt = 0; attempt < attempts; attempt++) {
|
||||
int x = random.nextInt(WIDTH);
|
||||
int y = random.nextInt(HEIGHT);
|
||||
int z = random.nextInt(DEPTH);
|
||||
if (get(x, y, z) != AIR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int filled = floodFill(x, y, z, AIR, MARKER);
|
||||
if (filled > 0 && filled < 640) {
|
||||
floodFill(x, y, z, MARKER, WATER);
|
||||
} else {
|
||||
floodFill(x, y, z, MARKER, AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int floodFill(int startX, int startY, int startZ, byte source, byte target) {
|
||||
if (!inside(startX, startY, startZ) || get(startX, startY, startZ) != source || source == target) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read = 0;
|
||||
int write = 0;
|
||||
int start = index(startX, startY, startZ);
|
||||
floodQueue[write++] = start;
|
||||
blocks[start] = target;
|
||||
boolean touchedBoundary = false;
|
||||
|
||||
while (read < write) {
|
||||
int current = floodQueue[read++];
|
||||
int x = current % WIDTH;
|
||||
int yz = current / WIDTH;
|
||||
int z = yz % DEPTH;
|
||||
int y = yz / DEPTH;
|
||||
touchedBoundary |= x == 0 || x == WIDTH - 1 || z == 0 || z == DEPTH - 1 || y == 0 || y == HEIGHT - 1;
|
||||
|
||||
write = enqueueIfSource(write, x - 1, y, z, source, target);
|
||||
write = enqueueIfSource(write, x + 1, y, z, source, target);
|
||||
write = enqueueIfSource(write, x, y, z - 1, source, target);
|
||||
write = enqueueIfSource(write, x, y, z + 1, source, target);
|
||||
write = enqueueIfSource(write, x, y - 1, z, source, target);
|
||||
}
|
||||
|
||||
return touchedBoundary ? -1 : write;
|
||||
}
|
||||
|
||||
private int enqueueIfSource(int write, int x, int y, int z, byte source, byte target) {
|
||||
if (!inside(x, y, z)) {
|
||||
return write;
|
||||
}
|
||||
int position = index(x, y, z);
|
||||
if (blocks[position] == source) {
|
||||
blocks[position] = target;
|
||||
floodQueue[write++] = position;
|
||||
}
|
||||
return write;
|
||||
}
|
||||
|
||||
private void growGrass() {
|
||||
for (int x = 0; x < WIDTH; x++) {
|
||||
for (int z = 0; z < DEPTH; z++) {
|
||||
for (int y = 0; y < HEIGHT - 1; y++) {
|
||||
if (get(x, y, z) == DIRT && !isOpaque(get(x, y + 1, z))) {
|
||||
set(x, y, z, GRASS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void growTrees(Random random) {
|
||||
int groups = WIDTH * DEPTH * HEIGHT / 80000;
|
||||
for (int group = 0; group < groups; group++) {
|
||||
int originX = random.nextInt(WIDTH);
|
||||
int originY = random.nextInt(HEIGHT);
|
||||
int originZ = random.nextInt(DEPTH);
|
||||
for (int patch = 0; patch < 25; patch++) {
|
||||
int x = originX;
|
||||
int y = originY;
|
||||
int z = originZ;
|
||||
for (int attempt = 0; attempt < 20; attempt++) {
|
||||
x += random.nextInt(12) - random.nextInt(12);
|
||||
y += random.nextInt(3) - random.nextInt(6);
|
||||
z += random.nextInt(12) - random.nextInt(12);
|
||||
if (inside(x, y, z)) {
|
||||
growTree(random, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean growTree(Random random, int x, int y, int z) {
|
||||
int logs = random.nextInt(3) + 4;
|
||||
if (y <= 0 || y + logs + 1 > HEIGHT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int blockY = y; blockY < y + 2 + logs; blockY++) {
|
||||
int radius = blockY == y ? 0 : blockY >= y + logs - 1 ? 2 : 1;
|
||||
for (int blockX = x - radius; blockX <= x + radius; blockX++) {
|
||||
for (int blockZ = z - radius; blockZ <= z + radius; blockZ++) {
|
||||
if (!inside(blockX, blockY, blockZ) || get(blockX, blockY, blockZ) != AIR) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte ground = get(x, y - 1, z);
|
||||
if ((ground != GRASS && ground != DIRT) || y >= HEIGHT - logs - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set(x, y - 1, z, DIRT);
|
||||
for (int blockY = y - 3 + logs; blockY <= y + logs; blockY++) {
|
||||
int distanceFromTop = blockY - (y + logs);
|
||||
int radius = 1 - distanceFromTop / 2;
|
||||
for (int blockX = x - radius; blockX <= x + radius; blockX++) {
|
||||
for (int blockZ = z - radius; blockZ <= z + radius; blockZ++) {
|
||||
boolean corner = Math.abs(blockX - x) == radius && Math.abs(blockZ - z) == radius;
|
||||
if ((!corner || random.nextInt(2) == 0 || distanceFromTop == 0)
|
||||
&& !isOpaque(get(blockX, blockY, blockZ))) {
|
||||
set(blockX, blockY, blockZ, OAK_LEAVES);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int log = 0; log < logs; log++) {
|
||||
if (!isOpaque(get(x, y + log, z))) {
|
||||
set(x, y + log, z, OAK_LOG);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void populatePlants(Random random, byte plant, int frequency) {
|
||||
int groups = WIDTH * DEPTH * HEIGHT * frequency / 1_600_000;
|
||||
for (int group = 0; group < groups; group++) {
|
||||
int originX = random.nextInt(WIDTH);
|
||||
int originY = random.nextInt(HEIGHT);
|
||||
int originZ = random.nextInt(DEPTH);
|
||||
for (int patch = 0; patch < 10; patch++) {
|
||||
int x = originX;
|
||||
int y = originY;
|
||||
int z = originZ;
|
||||
for (int attempt = 0; attempt < 10; attempt++) {
|
||||
x += random.nextInt(4) - random.nextInt(4);
|
||||
y += random.nextInt(2) - random.nextInt(2);
|
||||
z += random.nextInt(4) - random.nextInt(4);
|
||||
if (canPlant(plant, x, y, z)) {
|
||||
set(x, y, z, plant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canPlant(byte plant, int x, int y, int z) {
|
||||
if (!inside(x, y, z) || y <= 0 || get(x, y, z) != AIR) {
|
||||
return false;
|
||||
}
|
||||
byte below = get(x, y - 1, z);
|
||||
if (plant == DANDELION || plant == POPPY) {
|
||||
return below == GRASS || below == DIRT;
|
||||
}
|
||||
return below == GRASS || below == DIRT || below == STONE;
|
||||
}
|
||||
|
||||
private int[] findSpawn(long seed) {
|
||||
Random spawnRandom = new Random(seed ^ 0x49A4F1D3C2B7E659L);
|
||||
for (int attempt = 0; attempt < 10_000; attempt++) {
|
||||
int x = spawnRandom.nextInt(WIDTH / 2) + WIDTH / 4;
|
||||
int z = spawnRandom.nextInt(DEPTH / 2) + DEPTH / 4;
|
||||
int y = firstUncoveredBlock(x, z) + 1;
|
||||
|
||||
if (y < 4 || y <= WATER_LEVEL || !clearSpawnVolume(x, y, z)) {
|
||||
continue;
|
||||
}
|
||||
return new int[] { x, y, z };
|
||||
}
|
||||
return new int[] { WIDTH / 2, HEIGHT - 6, DEPTH / 2 };
|
||||
}
|
||||
|
||||
private int firstUncoveredBlock(int x, int z) {
|
||||
int y = HEIGHT;
|
||||
while (y > 0 && get(x, y - 1, z) == AIR) {
|
||||
y--;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
private boolean clearSpawnVolume(int x, int y, int z) {
|
||||
for (int blockX = x - 3; blockX <= x + 3; blockX++) {
|
||||
for (int blockZ = z - 5; blockZ <= z + 3; blockZ++) {
|
||||
if (!isOpaque(get(blockX, y - 2, blockZ))) {
|
||||
return false;
|
||||
}
|
||||
for (int blockY = y - 1; blockY <= y + 2; blockY++) {
|
||||
if (get(blockX, blockY, blockZ) != AIR) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void generateSpawnHouse(int x, int y, int z) {
|
||||
for (int blockX = x - 3; blockX <= x + 3; blockX++) {
|
||||
for (int blockY = y - 2; blockY <= y + 2; blockY++) {
|
||||
for (int blockZ = z - 3; blockZ <= z + 3; blockZ++) {
|
||||
byte block = blockY < y - 1 ? OBSIDIAN : AIR;
|
||||
boolean shell = blockX == x - 3 || blockX == x + 3
|
||||
|| blockZ == z - 3 || blockZ == z + 3
|
||||
|| blockY == y - 2 || blockY == y + 2;
|
||||
|
||||
if (shell) {
|
||||
block = blockY >= y - 1 ? OAK_PLANKS : STONE;
|
||||
}
|
||||
if (blockZ == z - 3 && blockX == x && blockY >= y - 1 && blockY <= y) {
|
||||
block = AIR;
|
||||
}
|
||||
set(blockX, blockY, blockZ, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Standing torches one block lower remain valid in the modern block engine.
|
||||
set(x - 2, y - 1, z, TORCH);
|
||||
set(x + 2, y - 1, z, TORCH);
|
||||
}
|
||||
|
||||
private BlockPos findPortalArrival() {
|
||||
int centerX = spawn[0];
|
||||
int centerZ = spawn[2];
|
||||
for (int radius = 10; radius < WIDTH / 2; radius++) {
|
||||
for (int dx = -radius; dx <= radius; dx++) {
|
||||
for (int dz = -radius; dz <= radius; dz++) {
|
||||
if (Math.abs(dx) != radius && Math.abs(dz) != radius) continue;
|
||||
int x = centerX + dx;
|
||||
int z = centerZ + dz;
|
||||
int y = firstUncoveredBlock(x, z);
|
||||
if (safePortalColumn(x, y, z)) {
|
||||
return new BlockPos(x + MIN_X, y, z + MIN_Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Indev island has no safe portal arrival outside its house");
|
||||
}
|
||||
|
||||
private boolean safePortalColumn(int x, int y, int z) {
|
||||
if (x < 2 || x >= WIDTH - 2 || z < 2 || z >= DEPTH - 2 || y <= WATER_LEVEL || y >= HEIGHT - 5) {
|
||||
return false;
|
||||
}
|
||||
byte floor = get(x, y - 1, z);
|
||||
if (!isOpaque(floor) || floor == OBSIDIAN || floor == OAK_PLANKS) return false;
|
||||
for (int offset = 0; offset <= 4; offset++) {
|
||||
byte block = get(x, y + offset, z);
|
||||
if (block != AIR && block != DANDELION && block != POPPY
|
||||
&& block != BROWN_MUSHROOM && block != RED_MUSHROOM) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean inside(int x, int y, int z) {
|
||||
return x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT && z >= 0 && z < DEPTH;
|
||||
}
|
||||
|
||||
private static int index(int x, int y, int z) {
|
||||
return (y * DEPTH + z) * WIDTH + x;
|
||||
}
|
||||
|
||||
private static boolean isOpaque(byte block) {
|
||||
return block != AIR && block != WATER && block != LAVA
|
||||
&& block != OAK_LEAVES && block != DANDELION && block != POPPY
|
||||
&& block != BROWN_MUSHROOM && block != RED_MUSHROOM && block != TORCH;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Distort {
|
||||
private final Octaves source;
|
||||
private final Octaves distortion;
|
||||
|
||||
private Distort(Octaves source, Octaves distortion) {
|
||||
this.source = source;
|
||||
this.distortion = distortion;
|
||||
}
|
||||
|
||||
private double noise(double x, double z) {
|
||||
return source.noise(x + distortion.noise(x, z), z);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Octaves {
|
||||
private final Perlin[] octaves;
|
||||
|
||||
private Octaves(Random random, int count) {
|
||||
octaves = new Perlin[count];
|
||||
for (int index = 0; index < count; index++) {
|
||||
octaves[index] = new Perlin(random);
|
||||
}
|
||||
}
|
||||
|
||||
private double noise(double x, double z) {
|
||||
double value = 0.0D;
|
||||
double power = 1.0D;
|
||||
for (Perlin octave : octaves) {
|
||||
value += octave.noise(x / power, z / power) * power;
|
||||
power *= 2.0D;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Perlin {
|
||||
private final int[] permutations = new int[512];
|
||||
|
||||
private Perlin(Random random) {
|
||||
for (int index = 0; index < 256; index++) {
|
||||
permutations[index] = index;
|
||||
}
|
||||
for (int index = 0; index < 256; index++) {
|
||||
int swap = random.nextInt(256 - index) + index;
|
||||
int temporary = permutations[index];
|
||||
permutations[index] = permutations[swap];
|
||||
permutations[swap] = temporary;
|
||||
permutations[index + 256] = permutations[index];
|
||||
}
|
||||
}
|
||||
|
||||
private double noise(double x, double z) {
|
||||
int floorX = (int) Math.floor(x);
|
||||
int floorZ = (int) Math.floor(z);
|
||||
int gridX = floorX & 0xFF;
|
||||
int gridZ = floorZ & 0xFF;
|
||||
x -= floorX;
|
||||
z -= floorZ;
|
||||
double fadedX = fade(x);
|
||||
double fadedZ = fade(z);
|
||||
int a = permutations[gridX] + gridZ;
|
||||
int b = permutations[gridX + 1] + gridZ;
|
||||
|
||||
double near = lerp(fadedX,
|
||||
grad(permutations[permutations[a]], x, z, 0.0D),
|
||||
grad(permutations[permutations[b]], x - 1.0D, z, 0.0D));
|
||||
double far = lerp(fadedX,
|
||||
grad(permutations[permutations[a + 1]], x, z - 1.0D, 0.0D),
|
||||
grad(permutations[permutations[b + 1]], x - 1.0D, z - 1.0D, 0.0D));
|
||||
return lerp(fadedZ, near, far);
|
||||
}
|
||||
|
||||
private static double fade(double value) {
|
||||
return value * value * value * (value * (value * 6.0D - 15.0D) + 10.0D);
|
||||
}
|
||||
|
||||
private static double lerp(double amount, double start, double end) {
|
||||
return start + amount * (end - start);
|
||||
}
|
||||
|
||||
private static double grad(int hash, double x, double z, double y) {
|
||||
hash &= 0xF;
|
||||
double first = hash < 8 ? x : z;
|
||||
double second = hash < 4 ? z : hash != 12 && hash != 14 ? y : x;
|
||||
return ((hash & 1) == 0 ? first : -first) + ((hash & 2) == 0 ? second : -second);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -496,5 +496,6 @@
|
||||
"item.sanctuary.minecon_pickaxe_cape": "Minecon Pickaxe Cape",
|
||||
"item.sanctuary.minecon_2011_cape": "Minecon 2011 Cape",
|
||||
"item.sanctuary.mojang_classic_cape": "Mojang Classic Cape",
|
||||
"item.sanctuary.blue_scroll_cape": "Blue Scroll Cape"
|
||||
"item.sanctuary.blue_scroll_cape": "Blue Scroll Cape",
|
||||
"dimension.sanctuary.alpha": "Alpha / Indev Island"
|
||||
}
|
||||
|
||||
@@ -496,5 +496,6 @@
|
||||
"item.sanctuary.minecon_pickaxe_cape": "Cape pioche Minecon",
|
||||
"item.sanctuary.minecon_2011_cape": "Cape Minecon 2011",
|
||||
"item.sanctuary.mojang_classic_cape": "Cape Mojang classique",
|
||||
"item.sanctuary.blue_scroll_cape": "Cape parchemin bleu"
|
||||
"item.sanctuary.blue_scroll_cape": "Cape parchemin bleu",
|
||||
"dimension.sanctuary.alpha": "Île Alpha / Indev"
|
||||
}
|
||||
|
||||
@@ -452,5 +452,6 @@
|
||||
"item.sanctuary.minecon_pickaxe_cape": "Плащ кирки Minecon",
|
||||
"item.sanctuary.minecon_2011_cape": "Плащ Minecon 2011",
|
||||
"item.sanctuary.mojang_classic_cape": "Классический плащ Mojang",
|
||||
"item.sanctuary.blue_scroll_cape": "Плащ синего свитка"
|
||||
"item.sanctuary.blue_scroll_cape": "Плащ синего свитка",
|
||||
"dimension.sanctuary.alpha": "Остров Альфа / Indev"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"type": "sanctuary:alpha",
|
||||
"generator": {
|
||||
"type": "minecraft:noise",
|
||||
"biome_source": {
|
||||
"type": "minecraft:fixed",
|
||||
"biome": "sanctuary:alpha"
|
||||
},
|
||||
"settings": "sanctuary:alpha"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"ambient_light": 0.0,
|
||||
"attributes": {
|
||||
"minecraft:audio/ambient_sounds": {
|
||||
"mood": {
|
||||
"block_search_extent": 8,
|
||||
"offset": 2.0,
|
||||
"sound": "minecraft:ambient.cave",
|
||||
"tick_delay": 9000
|
||||
}
|
||||
},
|
||||
"minecraft:gameplay/bed_rule": {
|
||||
"can_set_spawn": "never",
|
||||
"can_sleep": "never"
|
||||
},
|
||||
"minecraft:gameplay/can_start_raid": false,
|
||||
"minecraft:gameplay/respawn_anchor_works": false,
|
||||
"minecraft:gameplay/sky_light_level": 15.0,
|
||||
"minecraft:gameplay/water_evaporates": false,
|
||||
"minecraft:visual/ambient_light_color": "#ffffff",
|
||||
"minecraft:visual/cloud_color": "#ffffffff",
|
||||
"minecraft:visual/fog_color": "#ffffff",
|
||||
"minecraft:visual/fog_end_distance": 128.0,
|
||||
"minecraft:visual/fog_start_distance": 16.0,
|
||||
"minecraft:visual/sky_color": "#99ccff",
|
||||
"minecraft:visual/sky_light_color": "#ffffff",
|
||||
"minecraft:visual/sky_light_factor": 1.0
|
||||
},
|
||||
"cardinal_light": "default",
|
||||
"coordinate_scale": 1.0,
|
||||
"has_ceiling": false,
|
||||
"has_ender_dragon_fight": false,
|
||||
"has_fixed_time": false,
|
||||
"has_skylight": true,
|
||||
"height": 64,
|
||||
"infiniburn": "#minecraft:infiniburn_overworld",
|
||||
"logical_height": 64,
|
||||
"min_y": 0,
|
||||
"monster_spawn_block_light_limit": 0,
|
||||
"monster_spawn_light_level": 7,
|
||||
"skybox": "overworld",
|
||||
"timelines": "#minecraft:in_overworld"
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"temperature": 0.8,
|
||||
"downfall": 0.4,
|
||||
"has_precipitation": true,
|
||||
"attributes": {
|
||||
"minecraft:audio/background_music": {
|
||||
"default": {
|
||||
"max_delay": 24000,
|
||||
"min_delay": 12000,
|
||||
"sound": "minecraft:music.overworld.forest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"effects": {
|
||||
"water_color": "#3f76e4",
|
||||
"water_fog_color": "#050533",
|
||||
"fog_color": "#ffffff",
|
||||
"sky_color": "#99ccff",
|
||||
"grass_color": "#7cbd6b",
|
||||
"foliage_color": "#48b518"
|
||||
},
|
||||
"creature_spawn_probability": 0.2,
|
||||
"spawners": {
|
||||
"ambient": [],
|
||||
"axolotls": [],
|
||||
"creature": [
|
||||
{ "type": "minecraft:pig", "maxCount": 4, "minCount": 2, "weight": 10 },
|
||||
{ "type": "minecraft:sheep", "maxCount": 4, "minCount": 2, "weight": 10 },
|
||||
{ "type": "minecraft:cow", "maxCount": 4, "minCount": 2, "weight": 8 },
|
||||
{ "type": "minecraft:chicken", "maxCount": 4, "minCount": 2, "weight": 8 }
|
||||
],
|
||||
"misc": [],
|
||||
"monster": [
|
||||
{ "type": "minecraft:zombie", "maxCount": 4, "minCount": 1, "weight": 10 },
|
||||
{ "type": "minecraft:skeleton", "maxCount": 4, "minCount": 1, "weight": 10 },
|
||||
{ "type": "minecraft:spider", "maxCount": 4, "minCount": 1, "weight": 10 },
|
||||
{ "type": "minecraft:creeper", "maxCount": 4, "minCount": 1, "weight": 10 }
|
||||
],
|
||||
"underground_water_creature": [],
|
||||
"water_ambient": [],
|
||||
"water_creature": []
|
||||
},
|
||||
"spawn_costs": {},
|
||||
"carvers": [],
|
||||
"features": [
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
["sanctuary:alpha_indev_chunk"],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[]
|
||||
]
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "sanctuary:alpha_indev_chunk",
|
||||
"config": {}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"aquifers_enabled": false,
|
||||
"default_block": {
|
||||
"Name": "minecraft:air"
|
||||
},
|
||||
"default_fluid": {
|
||||
"Name": "minecraft:air"
|
||||
},
|
||||
"disable_mob_generation": false,
|
||||
"legacy_random_source": false,
|
||||
"noise": {
|
||||
"height": 64,
|
||||
"min_y": 0,
|
||||
"size_horizontal": 1,
|
||||
"size_vertical": 2
|
||||
},
|
||||
"noise_router": {
|
||||
"barrier": 0.0,
|
||||
"continents": 0.0,
|
||||
"depth": 0.0,
|
||||
"erosion": 0.0,
|
||||
"final_density": -1.0,
|
||||
"fluid_level_floodedness": 0.0,
|
||||
"fluid_level_spread": 0.0,
|
||||
"lava": 0.0,
|
||||
"preliminary_surface_level": 0.0,
|
||||
"ridges": 0.0,
|
||||
"temperature": 0.0,
|
||||
"vegetation": 0.0,
|
||||
"vein_gap": 0.0,
|
||||
"vein_ridged": 0.0,
|
||||
"vein_toggle": 0.0
|
||||
},
|
||||
"ore_veins_enabled": false,
|
||||
"sea_level": 32,
|
||||
"spawn_target": [],
|
||||
"surface_rule": {
|
||||
"type": "minecraft:block",
|
||||
"result_state": {
|
||||
"Name": "minecraft:air"
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"feature": "sanctuary:alpha_indev_chunk",
|
||||
"placement": [
|
||||
{
|
||||
"type": "minecraft:count",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"type": "minecraft:biome"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -47,6 +47,17 @@
|
||||
"settings": "sanctuary:caverns"
|
||||
}
|
||||
},
|
||||
"sanctuary:alpha": {
|
||||
"type": "sanctuary:alpha",
|
||||
"generator": {
|
||||
"type": "minecraft:noise",
|
||||
"biome_source": {
|
||||
"type": "minecraft:fixed",
|
||||
"biome": "sanctuary:alpha"
|
||||
},
|
||||
"settings": "sanctuary:alpha"
|
||||
}
|
||||
},
|
||||
"minecraft:the_end": {
|
||||
"type": "minecraft:the_end",
|
||||
"generator": {
|
||||
|
||||
@@ -47,6 +47,17 @@
|
||||
"settings": "sanctuary:caverns"
|
||||
}
|
||||
},
|
||||
"sanctuary:alpha": {
|
||||
"type": "sanctuary:alpha",
|
||||
"generator": {
|
||||
"type": "minecraft:noise",
|
||||
"biome_source": {
|
||||
"type": "minecraft:fixed",
|
||||
"biome": "sanctuary:alpha"
|
||||
},
|
||||
"settings": "sanctuary:alpha"
|
||||
}
|
||||
},
|
||||
"minecraft:the_end": {
|
||||
"type": "minecraft:the_end",
|
||||
"generator": {
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package fr.koka99cab.sanctuary26.sanctuary.worldgen.feature;
|
||||
|
||||
import fr.koka99cab.sanctuary26.sanctuary.api.world.SanctuaryAlphaWorld;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
|
||||
/** Executable invariants for the deterministic, finite Indev island generator. */
|
||||
public final class AlphaIndevGeneratorSmoke {
|
||||
private static final long[] SEEDS = {
|
||||
0L, 1L, -1L, 26_200_044L, Long.MIN_VALUE, Long.MAX_VALUE
|
||||
};
|
||||
|
||||
private AlphaIndevGeneratorSmoke() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SharedConstants.tryDetectVersion();
|
||||
Bootstrap.bootStrap();
|
||||
require(SanctuaryAlphaWorld.WIDTH == 128, "Alpha width must remain 128 blocks");
|
||||
require(SanctuaryAlphaWorld.DEPTH == 128, "Alpha depth must remain 128 blocks");
|
||||
require(SanctuaryAlphaWorld.HEIGHT == 64, "Alpha height must remain 64 blocks");
|
||||
|
||||
long originalFingerprint = AlphaIndevChunkFeature.fingerprint(SEEDS[0]);
|
||||
for (long seed : SEEDS) {
|
||||
long fingerprint = AlphaIndevChunkFeature.fingerprint(seed);
|
||||
BlockPos residence = SanctuaryAlphaWorld.residence(seed);
|
||||
BlockPos arrival = SanctuaryAlphaWorld.portalArrival(seed);
|
||||
|
||||
require(fingerprint != 0L, "Generated island fingerprint must be non-zero");
|
||||
require(SanctuaryAlphaWorld.containsHorizontal(residence), "Residence left finite bounds");
|
||||
require(SanctuaryAlphaWorld.containsHorizontal(arrival), "Portal arrival left finite bounds");
|
||||
require(arrival.getY() > AlphaIndevChunkFeature.WATER_LEVEL,
|
||||
"Portal arrival must be above the historical water level");
|
||||
require(arrival.getY() < AlphaIndevChunkFeature.HEIGHT - 4,
|
||||
"Portal arrival must leave a four-block clear column");
|
||||
int distance = Math.max(Math.abs(arrival.getX() - residence.getX()),
|
||||
Math.abs(arrival.getZ() - residence.getZ()));
|
||||
require(distance >= 10, "Portal arrival must not overlap the historical house");
|
||||
}
|
||||
|
||||
// Six distinct seeds evict the first entry from the bounded cache. Rebuilding it
|
||||
// must still produce the exact same terrain, house and arrival contract.
|
||||
require(AlphaIndevChunkFeature.fingerprint(SEEDS[0]) == originalFingerprint,
|
||||
"Same seed changed after cache eviction");
|
||||
require(AlphaIndevChunkFeature.fingerprint(SEEDS[0])
|
||||
!= AlphaIndevChunkFeature.fingerprint(SEEDS[1]),
|
||||
"Different seeds unexpectedly generated the same island");
|
||||
}
|
||||
|
||||
private static void require(boolean condition, String message) {
|
||||
if (!condition) throw new AssertionError(message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user