From 6fc93ca73254335cb62e7c28f6c47bd0050a3a3c Mon Sep 17 00:00:00 2001 From: koka Date: Sun, 30 Aug 2026 06:51:22 +0200 Subject: [PATCH 1/3] fix(ambiance): preserve white disc native audio rate --- ambiance/WHITE_DISC.md | 8 +++-- ambiance/build.gradle | 13 ++++--- .../client/audio/LavaplayerAudioStream.java | 27 ++++++++++++++- .../client/audio/WhiteDiscAudioPlayer.java | 7 ++-- .../audio/LavaplayerAudioStreamSmoke.java | 34 +++++++++++++------ .../client/audio/WhiteDiscPlaybackSmoke.java | 3 +- gradle.properties | 2 +- 7 files changed, 71 insertions(+), 23 deletions(-) diff --git a/ambiance/WHITE_DISC.md b/ambiance/WHITE_DISC.md index 16cecf4..a1e7a44 100644 --- a/ambiance/WHITE_DISC.md +++ b/ambiance/WHITE_DISC.md @@ -16,8 +16,12 @@ jukebox vanilla. libre ; il est envoyé uniquement aux clients qui suivent le chunk et annoncent le canal ; - chaque client ouvre lui-même la source YouTube, refuse les directs et les vidéos de plus de trente minutes, et limite les lectures simultanées à quatre ; -- la lecture utilise le canal `RECORDS`, un flux PCM mono positionnel et une atténuation à - 64 blocs. Elle s’arrête lorsque le disque est éjecté, le chunk disparaît ou la session se ferme. +- la source AAC stéréo est décodée à 48 kHz puis convertie explicitement en PCM mono 16 bits + little-endian, échantillon gauche/droite par échantillon gauche/droite, afin de conserver la + vitesse et la hauteur originales tout en restant positionnelle ; +- OpenAL lit ce PCM à sa hauteur native `1.0` sur le canal `RECORDS`, avec une atténuation à + 64 blocs. La lecture s’arrête lorsque le disque est éjecté, le chunk disparaît ou la session se + ferme. Le disque ne crée aucune donnée persistante et ne demande aucune migration de sauvegarde. Ambiance conserve ses données v2 ; son protocole passe de 5 à 6. diff --git a/ambiance/build.gradle b/ambiance/build.gradle index a848e6c..5c41ee8 100644 --- a/ambiance/build.gradle +++ b/ambiance/build.gradle @@ -102,7 +102,7 @@ tasks.named("test") { tasks.register("verifyAmbiance") { group = "verification" - description = "Checks Ambiance alpha.21, including corrected white-disc pitch and Alpha textures." + description = "Checks Ambiance alpha.22, including native-rate white-disc audio 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")) @@ -161,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.21" + if (project.version.toString() != "0.0.0-alpha.22" || 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" @@ -364,15 +364,18 @@ tasks.register("verifyAmbiance") { || !javaText.contains('tickPendingStarts(client)') || !javaText.contains('client.level.dimension().equals(playback.dimension())') || !javaText.contains('MAXIMUM_TRACK_MILLIS = 30L * 60L * 1_000L') - || !javaText.contains('new Pcm16AudioDataFormat(1, LavaplayerAudioStream.SAMPLE_RATE') + || !javaText.contains('new Pcm16AudioDataFormat(LavaplayerAudioStream.SOURCE_CHANNELS,') || !javaText.contains('new YoutubeAudioSourceManager(false, new Ios())') || !javaText.contains('player.addListener(new AudioEventAdapter()') || !javaText.contains('failPlayback(client, key, failedPlayer)') || !javaText.contains('initialWaitAttempted') || !javaText.contains('CONTINUATION_FRAME_WAIT_MILLIS = 250L') || !javaText.contains('player.provide(waitMillis, TimeUnit.MILLISECONDS)') - || !whiteDiscAudioPlayer.contains('PLAYBACK_PITCH = 4.0F / 3.0F') + || !whiteDiscAudioPlayer.contains('PLAYBACK_PITCH = 1.0F') || whiteDiscAudioPlayer.count('channel.setPitch(PLAYBACK_PITCH)') != 2 + || !javaText.contains('SOURCE_CHANNELS = 2') + || !javaText.contains('downmixStereoFrame(frame.getData())') + || !javaText.contains('short mixed = (short) (((int) left + right) / SOURCE_CHANNELS)') || !whiteDiscAudioPlayer.contains('handle.execute(channel -> channel.stop())') || whiteDiscAudioPlayer.contains('.release()') || !whiteDiscPlaybackSmoke.contains('https://www.youtube.com/watch?v=Ue5ZBe-GzSM') @@ -472,7 +475,7 @@ tasks.register("verifyAlphaTextures") { include "**/*golden*days*.zip", "**/*golden*days*.jar" exclude "**/build/**", "**/.gradle/**", "**/.git/**" }.files - if (project.version.toString() != "0.0.0-alpha.21" + if (project.version.toString() != "0.0.0-alpha.22" || migration.alpha_textures?.destination != "sanctuary:alpha" || migration.alpha_textures?.client_only != true || migration.alpha_textures?.bundled_assets != false diff --git a/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java b/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java index 95d8f0e..488d48a 100644 --- a/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java +++ b/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java @@ -12,6 +12,10 @@ import net.minecraft.client.sounds.AudioStream; /** Adapts bounded mono PCM frames from Lavaplayer to Minecraft's streaming OpenAL channel. */ final class LavaplayerAudioStream implements AudioStream { static final int SAMPLE_RATE = 48_000; + static final int SOURCE_CHANNELS = 2; + static final int FRAME_SAMPLES = 960; + private static final int BYTES_PER_SAMPLE = Short.BYTES; + private static final int SOURCE_FRAME_SIZE = SOURCE_CHANNELS * BYTES_PER_SAMPLE; private static final long INITIAL_FRAME_WAIT_MILLIS = 2_000L; private static final long CONTINUATION_FRAME_WAIT_MILLIS = 250L; private static final AudioFormat FORMAT = @@ -65,7 +69,7 @@ final class LavaplayerAudioStream implements AudioStream { if (firstFrameTimecode < 0L) firstFrameTimecode = frame.getTimecode(); lastFrameTimecode = frame.getTimecode(); decodedFrames++; - pending = frame.getData(); + pending = downmixStereoFrame(frame.getData()); pendingOffset = 0; } if (output.position() == 0 && ended) return null; @@ -73,6 +77,27 @@ final class LavaplayerAudioStream implements AudioStream { return output; } + private static byte[] downmixStereoFrame(byte[] stereo) throws IOException { + if (stereo.length == 0 || stereo.length % SOURCE_FRAME_SIZE != 0) { + throw new IOException("Invalid stereo PCM frame length: " + stereo.length); + } + byte[] mono = new byte[stereo.length / SOURCE_CHANNELS]; + for (int sourceOffset = 0, targetOffset = 0; + sourceOffset < stereo.length; + sourceOffset += SOURCE_FRAME_SIZE, targetOffset += BYTES_PER_SAMPLE) { + short left = littleEndianSample(stereo, sourceOffset); + short right = littleEndianSample(stereo, sourceOffset + BYTES_PER_SAMPLE); + short mixed = (short) (((int) left + right) / SOURCE_CHANNELS); + mono[targetOffset] = (byte) mixed; + mono[targetOffset + 1] = (byte) (mixed >>> 8); + } + return mono; + } + + private static short littleEndianSample(byte[] pcm, int offset) { + return (short) (Byte.toUnsignedInt(pcm[offset]) | pcm[offset + 1] << 8); + } + private AudioFrame nextFrame() throws IOException { try { long waitMillis = initialWaitAttempted diff --git a/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscAudioPlayer.java b/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscAudioPlayer.java index bbae0e7..5200400 100644 --- a/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscAudioPlayer.java +++ b/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscAudioPlayer.java @@ -36,8 +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; + /** OpenAL must preserve the decoded music's native speed and pitch. */ + static final float PLAYBACK_PITCH = 1.0F; private static final DefaultAudioPlayerManager MANAGER = createManager(); private static final Map PENDING_STARTS = new HashMap<>(); private static final Map REQUESTS = new HashMap<>(); @@ -237,7 +237,8 @@ public final class WhiteDiscAudioPlayer { private static DefaultAudioPlayerManager createManager() { DefaultAudioPlayerManager manager = new DefaultAudioPlayerManager(); manager.getConfiguration().setOutputFormat( - new Pcm16AudioDataFormat(1, LavaplayerAudioStream.SAMPLE_RATE, 960, false)); + new Pcm16AudioDataFormat(LavaplayerAudioStream.SOURCE_CHANNELS, + LavaplayerAudioStream.SAMPLE_RATE, LavaplayerAudioStream.FRAME_SAMPLES, false)); manager.setFrameBufferDuration(5_000); manager.setItemLoaderThreadPoolSize(2); manager.registerSourceManager(new YoutubeAudioSourceManager(false, new Ios())); diff --git a/ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStreamSmoke.java b/ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStreamSmoke.java index 2150a02..8ae157c 100644 --- a/ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStreamSmoke.java +++ b/ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStreamSmoke.java @@ -7,7 +7,6 @@ import com.sedmelluq.discord.lavaplayer.track.playback.ImmutableAudioFrame; import java.lang.reflect.Proxy; import java.nio.ByteBuffer; import java.util.ArrayDeque; -import java.util.Arrays; import java.util.Queue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -15,22 +14,27 @@ import java.util.concurrent.atomic.AtomicInteger; /** Deterministic check for Minecraft's four one-second streaming buffers. */ public final class LavaplayerAudioStreamSmoke { private static final int FRAME_SAMPLES = 960; - private static final int FRAME_BYTES = FRAME_SAMPLES * 2; + private static final int SOURCE_FRAME_BYTES = FRAME_SAMPLES + * LavaplayerAudioStream.SOURCE_CHANNELS * Short.BYTES; private static final int FRAMES_PER_SECOND = LavaplayerAudioStream.SAMPLE_RATE / FRAME_SAMPLES; private 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"); + if (Math.abs(WhiteDiscAudioPlayer.PLAYBACK_PITCH - 1.0F) > 0.0001F) { + throw new IllegalStateException("The white-disc playback pitch is not native"); } Queue frames = new ArrayDeque<>(); Pcm16AudioDataFormat format = new Pcm16AudioDataFormat( - 1, LavaplayerAudioStream.SAMPLE_RATE, FRAME_SAMPLES, false); + LavaplayerAudioStream.SOURCE_CHANNELS, LavaplayerAudioStream.SAMPLE_RATE, + FRAME_SAMPLES, false); for (int index = 0; index < FRAMES_PER_SECOND; index++) { - byte[] data = new byte[FRAME_BYTES]; - Arrays.fill(data, (byte) (index + 1)); + byte[] data = new byte[SOURCE_FRAME_BYTES]; + for (int offset = 0; offset < data.length; offset += 4) { + putLittleEndian(data, offset, (short) (1_000 + index)); + putLittleEndian(data, offset + 2, (short) (3_000 + index)); + } frames.add(new ImmutableAudioFrame(index * 20L, data, 100, format)); } @@ -63,9 +67,14 @@ public final class LavaplayerAudioStreamSmoke { if (pcm == null || pcm.remaining() != LavaplayerAudioStream.SAMPLE_RATE * 2) { throw new IllegalStateException("The stream did not fill Minecraft's one-second buffer"); } - while (pcm.hasRemaining()) { - if (pcm.get() == 0) { - throw new IllegalStateException("The stream padded available PCM with silence"); + for (int frame = 0; frame < FRAMES_PER_SECOND; frame++) { + short expected = (short) (2_000 + frame); + for (int sample = 0; sample < FRAME_SAMPLES; sample++) { + int low = Byte.toUnsignedInt(pcm.get()); + short actual = (short) (low | pcm.get() << 8); + if (actual != expected) { + throw new IllegalStateException("Stereo PCM was not downmixed in sample order"); + } } } if (timedProvides.get() != FRAMES_PER_SECOND || nonBlockingProvides.get() != 0) { @@ -80,4 +89,9 @@ public final class LavaplayerAudioStreamSmoke { throw new IllegalStateException("Closing the stream did not destroy its player"); } } + + private static void putLittleEndian(byte[] data, int offset, short sample) { + data[offset] = (byte) sample; + data[offset + 1] = (byte) (sample >>> 8); + } } diff --git a/ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java b/ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java index e296197..1e5839d 100644 --- a/ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java +++ b/ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java @@ -23,7 +23,8 @@ public final class WhiteDiscPlaybackSmoke { public static void main(String[] args) throws Exception { DefaultAudioPlayerManager manager = new DefaultAudioPlayerManager(); manager.getConfiguration().setOutputFormat( - new Pcm16AudioDataFormat(1, LavaplayerAudioStream.SAMPLE_RATE, 960, false)); + new Pcm16AudioDataFormat(LavaplayerAudioStream.SOURCE_CHANNELS, + LavaplayerAudioStream.SAMPLE_RATE, LavaplayerAudioStream.FRAME_SAMPLES, false)); manager.registerSourceManager(new YoutubeAudioSourceManager(false, new Ios())); try { AudioTrack track = load(manager).get(30, TimeUnit.SECONDS); diff --git a/gradle.properties b/gradle.properties index 41a678b..c1b4268 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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.21 +ambiance_version=0.0.0-alpha.22 ambiance_lifecycle=active redstoner_version=0.0.0-alpha.11 redstoner_lifecycle=active -- 2.54.0 From e8dee9b7f8b496e7aa27d6c21e1163b9ec69424a Mon Sep 17 00:00:00 2001 From: koka Date: Sun, 30 Aug 2026 06:55:18 +0200 Subject: [PATCH 2/3] feat(redstoner): integrate storage terminal menu --- CHANGELOG.md | 13 + README.md | 4 +- build.gradle | 349 ++++++++++++------ gradle.properties | 4 +- ...19-storage-terminal-menu-to-alpha.220.json | 54 +++ pack/packwiz/index.toml | 4 +- pack/packwiz/pack.toml | 4 +- pack/prism/modrinth.index.json | 2 +- pack/release.json | 4 +- .../sanctuary26/redstoner/RedStonerMod.java | 2 + .../redstoner/block/StorageTerminalBlock.java | 4 +- .../redstoner/client/RedStonerClient.java | 13 +- .../client/gui/StorageTerminalScreen.java | 285 +++++--------- .../network/RedStonerNetworking.java | 29 +- .../network/StorageTerminalActionPayload.java | 56 --- .../StorageTerminalSnapshotPayload.java | 80 ---- .../redstoner/registry/RedStonerMenus.java | 23 ++ .../storage/StorageTerminalInventory.java | 7 +- .../storage/StorageTerminalMenu.java | 298 +++++++++++++++ .../storage/StorageTerminalRules.java | 13 +- .../storage/StorageTerminalService.java | 109 ------ redstoner/src/main/resources/fabric.mod.json | 2 +- .../storage/StorageTerminalSmoke.java | 27 +- 23 files changed, 758 insertions(+), 628 deletions(-) create mode 100644 pack/migrations/26.2.0-alpha.219-storage-terminal-menu-to-alpha.220.json delete mode 100644 redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/StorageTerminalActionPayload.java delete mode 100644 redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/StorageTerminalSnapshotPayload.java create mode 100644 redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/registry/RedStonerMenus.java create mode 100644 redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalMenu.java delete mode 100644 redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalService.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 9decd54..3620a5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,19 @@ 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.220` + +Module modifié : **Red-Stoner `0.0.0-alpha.12`**. Les neuf autres modules conservent leur version issue de l'alpha.219. + +- remplace l’écran propriétaire du terminal par un véritable menu de conteneur inspiré des coffres vanilla et composé avec le panneau d’inventaire Sanctuary ; +- supprime le bouton de fermeture dédié : Échap et la touche d’inventaire suivent désormais le comportement normal du jeu ; +- affiche et synchronise toutes les rangées d’inventaire débloquées par Sanctuary, d’une à six, y compris les deux rangées persistantes supplémentaires ; +- permet le retrait par clic gauche, le retrait unitaire par clic droit et le retrait vers l’inventaire par shift-clic ; un clic avec une pile portée ou un shift-clic depuis l’inventaire dépose dans le réseau ; +- conserve les 54 cases comme une vue agrégée non réorganisable et affiche les quantités exactes sans créer de stockage virtuel ; +- dépose dans le premier coffre ou baril disponible selon l’ordre déterministe de découverte, remplit d’abord ses piles compatibles puis ses cases vides et ne passe au stockage suivant qu’en cas de besoin ; +- supprime les anciens payloads spécifiques au terminal au profit de la synchronisation native des menus, tout en gardant la distance, la topologie et les transferts sous autorité serveur ; +- conserve les données Red-Stoner v3 et les sauvegardes existantes ; le protocole réseau Red-Stoner passe de 6 à 7, sans nouveau monde ni réinitialisation. + ## `26.2.0-alpha.219` 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. diff --git a/README.md b/README.md index 2c940bd..3def907 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,12 @@ 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.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. +Version courante du pack distribué : **`26.2.0-alpha.220`**. Cette release distribue Red-Stoner **`0.0.0-alpha.12`** ; les neuf autres modules conservent leur version issue de l'alpha.219. 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.220 transforme le terminal de stockage en véritable menu de conteneur, sans bouton de fermeture propriétaire. Les clics gauche/droit et shift-clic permettent maintenant de retirer ou déposer des piles depuis toutes les rangées d’inventaire débloquées par Sanctuary, jusqu’à six ; la grille agrégée reste non réorganisable et remplit chaque coffre ou baril dans l’ordre de découverte avant de passer au suivant. + 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. diff --git a/build.gradle b/build.gradle index cf63688..f29b5e9 100644 --- a/build.gradle +++ b/build.gradle @@ -1505,7 +1505,7 @@ tasks.register("verifyWorkspace") { || personalComputerMigration.compatibility?.redstoner_target_data_version != 3 || personalComputerMigration.compatibility?.redstoner_target_network_protocol != 5 || redstonerManifest.custom?.sanctuary26?.data_version != 3 - || redstonerManifest.custom?.sanctuary26?.network_protocol != 6 + || redstonerManifest.custom?.sanctuary26?.network_protocol != 7 || sanctuaryManifest.custom?.sanctuary26?.data_version < 8 || !sanctuaryIdentity.contains('SAVE_KEY = "server_identity"') || !personalComputerJava.contains('SAVE_KEY = "personal_computers"') @@ -3437,7 +3437,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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 @@ -3487,9 +3487,9 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || rootProject.anotherworld_version != "0.0.0-alpha.55" - || rootProject.redstoner_version != "0.0.0-alpha.11" + || rootProject.redstoner_version != "0.0.0-alpha.12" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version || migration.source?.pack_version != "26.2.0-alpha.191" || migration.source?.modules != [anotherworld: "0.0.0-alpha.48", redstoner: "0.0.0-alpha.9"] @@ -3994,6 +3994,7 @@ project(":redstoner") { 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.217-storage-terminal-to-alpha.218.json")) + inputs.file(rootProject.file("pack/migrations/26.2.0-alpha.219-storage-terminal-menu-to-alpha.220.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") @@ -4014,6 +4015,8 @@ project(":redstoner") { "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.217-storage-terminal-to-alpha.218.json")) + def terminalMenuMigration = new JsonSlurper().parse(rootProject.file( + "pack/migrations/26.2.0-alpha.219-storage-terminal-menu-to-alpha.220.json")) def requiredIds = [ "eight_bit_computer", "controller", "personal_computer", "drawer", "particuleur", "storage_terminal"] def missingIds = requiredIds.findAll { !registry.contains("id(\"${it}\")") } @@ -4040,8 +4043,10 @@ project(":redstoner") { 'class ParticuleurBlock', 'implements WorldlyContainer', '"Catalyst"', 'getBestNeighborSignal', 'ParticuleurParticleTable', 'side != getBlockState().getValue(ParticuleurBlock.FACING)', - 'id("s2c/storage_terminal_snapshot")', 'id("c2s/storage_terminal_action")', - 'class StorageTerminalBlock', 'MAX_CONTAINERS = 128', 'PAGE_SIZE = 54', + 'class StorageTerminalBlock', 'class StorageTerminalMenu', + 'extends AbstractContainerMenu', 'addStandardInventorySlots', + 'SanctuaryPlayerInventoryView.unlockedRows', 'MenuScreens.register', + 'MAX_CONTAINERS = 128', 'PAGE_SIZE = 54', 'ItemStack.isSameItemSameComponents', 'level.hasChunkAt(pos)' ] def missingContracts = requiredContracts.findAll { !javaText.contains(it) } @@ -4098,9 +4103,9 @@ project(":redstoner") { "src/main/resources/data/redstoner/recipe/controller.json")) def terminalRecipe = new JsonSlurper().parse(file( "src/main/resources/data/redstoner/recipe/storage_terminal.json")) - if (project.version.toString() != "0.0.0-alpha.11" + if (project.version.toString() != "0.0.0-alpha.12" || manifest.custom?.sanctuary26?.data_version != 3 - || manifest.custom?.sanctuary26?.network_protocol != 6 + || manifest.custom?.sanctuary26?.network_protocol != 7 || 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"] @@ -4123,12 +4128,23 @@ project(":redstoner") { || terminalMigration.compatibility?.redstoner_data_version != 3 || terminalMigration.compatibility?.redstoner_source_network_protocol != 5 || terminalMigration.compatibility?.redstoner_target_network_protocol != 6 + || terminalMenuMigration.source?.pack_version != "26.2.0-alpha.219" + || terminalMenuMigration.source?.modules?.redstoner != "0.0.0-alpha.11" + || terminalMenuMigration.target?.pack_version != "26.2.0-alpha.220" + || terminalMenuMigration.target?.modules?.redstoner != "0.0.0-alpha.12" + || terminalMenuMigration.storage_terminal_menu?.native_container_menu != true + || terminalMenuMigration.storage_terminal_menu?.maximum_player_inventory_rows != 6 + || terminalMenuMigration.storage_terminal_menu?.terminal_slots_reorderable != false + || terminalMenuMigration.storage_terminal_menu?.quantity_data_words_per_slot != 2 + || terminalMenuMigration.storage_terminal_menu?.deposit_order != "first_discovered_container" + || terminalMenuMigration.compatibility?.redstoner_source_network_protocol != 6 + || terminalMenuMigration.compatibility?.redstoner_target_network_protocol != 7 || terminalRecipe.pattern != ["PGP", "GCG", "PTP"] || terminalRecipe.key != [ P: "anotherworld:silver_plate", G: "minecraft:tinted_glass", C: "redstoner:controller", T: "anotherworld:titanium_ingot"] || terminalRecipe.result != [id: "redstoner:storage_terminal", count: 1]) { - throw new GradleException("Red-Stoner alpha.11 Storage Terminal contract is incomplete") + throw new GradleException("Red-Stoner alpha.12 Storage Terminal menu contract is incomplete") } if (file("src/main/resources/data/redstoner/recipe/personal_computer.json").exists() || file("src/main/resources/data/redstoner/recipe/drawer.json").exists() @@ -4259,7 +4275,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || rootProject.onlyfun_version != "0.0.0-alpha.25" || rootProject.sanctuary_version != "0.0.0-alpha.122" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version @@ -4304,7 +4320,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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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,7 +4369,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || rootProject.onlyfun_version != "0.0.0-alpha.25" || rootProject.sanctuary_version != "0.0.0-alpha.122" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version @@ -4399,7 +4415,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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || migration.source?.pack_version != "26.2.0-alpha.195" || migration.target?.pack_version != "26.2.0-alpha.196" || migration.target?.modules != [ @@ -4417,10 +4433,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.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"')) { + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" + || !packwiz.contains('version = "26.2.0-alpha.220"')) { throw new GradleException("The alpha.196 culinary, mailbox and grapple release contract is incomplete") } } @@ -4445,7 +4461,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || rootProject.itsalive_version != "0.0.0-alpha.36" || rootProject.sanctuary_version != "0.0.0-alpha.122" || migration.source?.pack_version != "26.2.0-alpha.196" @@ -4465,10 +4481,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.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"')) { + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" + || !packwiz.contains('version = "26.2.0-alpha.220"')) { throw new GradleException("The alpha.197 quest-request and cauldron-batch release contract is incomplete") } } @@ -4495,7 +4511,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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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 +4530,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.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"') + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" + || !packwiz.contains('version = "26.2.0-alpha.220"') || !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.36.jar"')) { throw new GradleException("The alpha.198 fermentation barrel release contract is incomplete") } @@ -4545,7 +4561,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || rootProject.itsalive_version != "0.0.0-alpha.36" || rootProject.sanctuary_version != "0.0.0-alpha.122" || migration.source?.pack_version != "26.2.0-alpha.198" @@ -4559,10 +4575,10 @@ 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.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"') + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" + || !packwiz.contains('version = "26.2.0-alpha.220"') || !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.36.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,7 +4616,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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" @@ -4634,10 +4650,10 @@ tasks.register("verifyWeatherTntAmbianceRelease") { || !weatherTnt.contains("AmbianceDailyWeather.CLEAR") || !weatherTnt.contains("CLEAR_WEATHER_TICKS = 864_000") || weatherTnt.contains("setWeatherParameters") - || 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"') + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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,7 +4682,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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" @@ -4681,10 +4697,10 @@ 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.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"') + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" + || !packwiz.contains('version = "26.2.0-alpha.220"') || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.122.jar"')) { throw new GradleException("The alpha.201 quest-request escrow release is incomplete") } @@ -4720,7 +4736,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || rootProject.anotherworld_version != "0.0.0-alpha.55" || rootProject.itsalive_version != "0.0.0-alpha.36" || rootProject.iliketomoveit_version != "0.0.0-alpha.16" @@ -4760,10 +4776,10 @@ 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.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"') + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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.16.jar"') @@ -4880,7 +4896,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || rootProject.anotherworld_version != "0.0.0-alpha.55" || rootProject.sanctuary_version != "0.0.0-alpha.122" || migration.schema_version != 1 @@ -5072,7 +5088,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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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 +5106,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.219.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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 +5134,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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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 +5160,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.219.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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 +5188,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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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 +5217,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.219.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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 +5246,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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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 +5269,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.219.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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 +5298,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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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 +5328,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.219.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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,7 +5386,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || rootProject.itsalive_version != "0.0.0-alpha.36" || rootProject.ambiance_version != "0.0.0-alpha.21" || migration.issue != 35 @@ -5622,7 +5638,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || rootProject.ambiance_version != "0.0.0-alpha.21" || rootProject.itsalive_version != "0.0.0-alpha.36" || rootProject.onlyfun_version != "0.0.0-alpha.25" @@ -5670,9 +5686,9 @@ 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.219.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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"') @@ -5740,7 +5756,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || rootProject.sanctuary_version != "0.0.0-alpha.122" || rootProject.onlyfun_version != "0.0.0-alpha.25" || rootProject.iliketomoveit_version != currentModules.iliketomoveit @@ -5786,10 +5802,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.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"') + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" + || !packwiz.contains('version = "26.2.0-alpha.220"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || jeiFiles.size() != 1 @@ -5865,7 +5881,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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || workspaceModules.any { id, version -> rootProject.property("${id}_version") != version } || migration.source?.pack_version != "26.2.0-alpha.210" || migration.source?.modules != expectedSource @@ -5893,9 +5909,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.219.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || prism.files?.size() != 5 @@ -5903,7 +5919,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.219`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { throw new GradleException("The alpha.211 Abjection and gameplay-polish release is incomplete") } } @@ -5937,7 +5953,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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"] @@ -5959,16 +5975,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.219" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack" - || prism.versionId != "26.2.0-alpha.219" + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" || prism.files?.size() != 5 || jeiFiles.size() != 1 - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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.219`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { throw new GradleException("The alpha.212 Black Market startup-fix release is incomplete") } } @@ -6002,7 +6018,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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"] @@ -6026,16 +6042,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.219" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack" - || prism.versionId != "26.2.0-alpha.219" + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" || prism.files?.size() != 5 || jeiFiles.size() != 1 - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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.219`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { throw new GradleException("The alpha.213 Ambiance startup-fix release is incomplete") } } @@ -6070,7 +6086,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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"] @@ -6099,16 +6115,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.219" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack" - || prism.versionId != "26.2.0-alpha.219" + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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.219`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { throw new GradleException("The alpha.214 white-disc solo synchronization release is incomplete") } } @@ -6149,7 +6165,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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"] @@ -6189,16 +6205,16 @@ tasks.register("verifyAlpha215Release") { || !playbackSmoke.contains("https://www.youtube.com/watch?v=Ue5ZBe-GzSM") || !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" + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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.219`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { throw new GradleException("The alpha.215 resilient white-disc playback release is incomplete") } } @@ -6243,7 +6259,7 @@ 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.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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"] @@ -6285,16 +6301,16 @@ tasks.register("verifyAlpha216Release") { || !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.219" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.219.mrpack" - || prism.versionId != "26.2.0-alpha.219" + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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.219`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { throw new GradleException("The alpha.216 white-disc audio-quality release is incomplete") } } @@ -6329,7 +6345,7 @@ tasks.register("verifyAlpha217Release") { "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" + if (rootProject.pack_version != "26.2.0-alpha.220" || 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"] @@ -6360,16 +6376,16 @@ tasks.register("verifyAlpha217Release") { || !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" + || release.pack_version != "26.2.0-alpha.220" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != "26.2.0-alpha.220" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || !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`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { throw new GradleException("The alpha.217 white-disc pitch release is incomplete") } } @@ -6416,7 +6432,7 @@ tasks.register("verifyAlpha218Release") { 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 currentModules = targetModules + [ + def currentModules = targetModules + [redstoner: "0.0.0-alpha.12", 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\"" @@ -6424,7 +6440,7 @@ tasks.register("verifyAlpha218Release") { def obsoleteJars = sourceModules.collect { id, version -> "file = \"mods/${id}-${version}.jar\"" } - if (rootProject.pack_version != "26.2.0-alpha.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || currentModules.any { id, version -> rootProject.property("${id}_version") != version } || migration.source?.pack_version != "26.2.0-alpha.217" || migration.source?.modules != sourceModules @@ -6446,24 +6462,24 @@ tasks.register("verifyAlpha218Release") { || migration.distribution?.packwiz_index_refreshed != true || migration.distribution?.prism_modrinth_index_updated != true || manifests.redstoner.custom?.sanctuary26?.data_version != 3 - || manifests.redstoner.custom?.sanctuary26?.network_protocol != 6 + || manifests.redstoner.custom?.sanctuary26?.network_protocol != 7 || manifests.onlyfun.custom?.sanctuary26?.data_version != 2 || manifests.onlyfun.custom?.sanctuary26?.network_protocol != 3 || manifests.sanctuary.custom?.sanctuary26?.data_version != 11 || manifests.sanctuary.custom?.sanctuary26?.network_protocol != 22 || !rules.contains("MAX_CONTAINERS = 128") || !rules.contains("PAGE_SIZE = 54") - || !networking.contains("PROTOCOL_VERSION = 6") + || !networking.contains("PROTOCOL_VERSION = 7") || !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.219.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || !changelog.contains("## `26.2.0-alpha.218`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.219`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { throw new GradleException("The alpha.218 Storage Terminal release is incomplete") } } @@ -6517,7 +6533,7 @@ tasks.register("verifyAlpha219Release") { include "**/*golden*days*.zip", "**/*golden*days*.jar" exclude "**/build/**", "**/.gradle/**", "**/.git/**" }.files - if (rootProject.pack_version != "26.2.0-alpha.219" + if (rootProject.pack_version != "26.2.0-alpha.220" || targetModules.any { id, version -> rootProject.property("${id}_version") != version } || migration.source?.pack_version != "26.2.0-alpha.218" || migration.source?.modules != sourceModules @@ -6549,20 +6565,106 @@ tasks.register("verifyAlpha219Release") { || 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" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" || prism.versionId != rootProject.pack_version || prism.files.any { it.path.toLowerCase().contains("golden-days") } - || !packwiz.contains('version = "26.2.0-alpha.219"') + || !packwiz.contains('version = "26.2.0-alpha.220"') || 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`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { throw new GradleException("The alpha.219 finite Alpha/Indev release is incomplete") } } } +tasks.register("verifyAlpha220Release") { + group = "verification" + description = "Checks the Sanctuary 26.2.0-alpha.220 Storage Terminal container-menu release." + inputs.file(file("pack/migrations/26.2.0-alpha.219-storage-terminal-menu-to-alpha.220.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("redstoner/src/main/resources/fabric.mod.json")) + inputs.file(file("redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalMenu.java")) + inputs.file(file("redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalInventory.java")) + inputs.file(file("redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/gui/StorageTerminalScreen.java")) + inputs.file(file("redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/RedStonerNetworking.java")) + doLast { + def migration = new JsonSlurper().parse(file( + "pack/migrations/26.2.0-alpha.219-storage-terminal-menu-to-alpha.220.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("redstoner/src/main/resources/fabric.mod.json")) + def menu = file( + "redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalMenu.java").text + def inventory = file( + "redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalInventory.java").text + def screen = file( + "redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/gui/StorageTerminalScreen.java").text + def networking = file( + "redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/RedStonerNetworking.java").text + if (rootProject.pack_version != "26.2.0-alpha.220" + || rootProject.redstoner_version != "0.0.0-alpha.12" + || migration.source?.pack_version != "26.2.0-alpha.219" + || migration.source?.modules != [redstoner: "0.0.0-alpha.11"] + || migration.target?.pack_version != "26.2.0-alpha.220" + || migration.target?.modules != [redstoner: "0.0.0-alpha.12"] + || migration.storage_terminal_menu?.owner != "redstoner" + || migration.storage_terminal_menu?.menu_type != "redstoner:storage_terminal" + || migration.storage_terminal_menu?.native_container_menu != true + || migration.storage_terminal_menu?.dedicated_close_button != false + || migration.storage_terminal_menu?.terminal_slots != 54 + || migration.storage_terminal_menu?.terminal_slots_reorderable != false + || migration.storage_terminal_menu?.quantity_data_words_per_slot != 2 + || migration.storage_terminal_menu?.minimum_player_inventory_rows != 1 + || migration.storage_terminal_menu?.maximum_player_inventory_rows != 6 + || migration.storage_terminal_menu?.inventory_rows_authority != "sanctuary_progression" + || migration.storage_terminal_menu?.deposit_order != "first_discovered_container" + || migration.storage_terminal_menu?.per_container_order != ["compatible_stacks", "empty_slots"] + || migration.storage_terminal_menu?.server_authoritative_transfers != true + || migration.storage_terminal_menu?.vanilla_menu_synchronization != true + || migration.storage_terminal_menu?.legacy_terminal_payloads_removed != true + || migration.compatibility?.existing_saves_supported != true + || migration.compatibility?.redstoner_data_version != 3 + || migration.compatibility?.redstoner_source_network_protocol != 6 + || migration.compatibility?.redstoner_target_network_protocol != 7 + || manifest.custom?.sanctuary26?.data_version != 3 + || manifest.custom?.sanctuary26?.network_protocol != 7 + || !menu.contains("extends AbstractContainerMenu") + || !menu.contains("addStandardInventorySlots") + || !menu.contains("SanctuaryPlayerInventoryView.unlockedRows") + || !menu.contains("ContainerInput.QUICK_MOVE") + || !menu.contains("ContainerInput.PICKUP") + || !menu.contains("class TerminalDisplaySlot") + || !inventory.contains("for (Container container : containers)") + || !screen.contains("extends AbstractContainerScreen") + || !screen.contains("textures/gui/container/generic_54.png") + || screen.contains("Button.builder") + || !networking.contains("PROTOCOL_VERSION = 7") + || networking.contains("storage_terminal_snapshot") + || networking.contains("storage_terminal_action") + || release.pack_version != rootProject.pack_version + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || prism.versionId != rootProject.pack_version + || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwizIndex.contains('file = "mods/redstoner-0.0.0-alpha.12.jar"') + || packwizIndex.contains('file = "mods/redstoner-0.0.0-alpha.11.jar"') + || !changelog.contains("## `26.2.0-alpha.220`") + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { + throw new GradleException("The alpha.220 Storage Terminal menu release is incomplete") + } + } +} + tasks.named("verifyWorkspace") { dependsOn tasks.named("verifyAlpha213Release") dependsOn tasks.named("verifyAlpha214Release") @@ -6571,6 +6673,7 @@ tasks.named("verifyWorkspace") { dependsOn tasks.named("verifyAlpha217Release") dependsOn tasks.named("verifyAlpha218Release") dependsOn tasks.named("verifyAlpha219Release") + dependsOn tasks.named("verifyAlpha220Release") } tasks.named("check") { diff --git a/gradle.properties b/gradle.properties index 41a678b..0ed1278 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ mod_version=0.0.0-alpha.0 module_lifecycle=standby ambiance_version=0.0.0-alpha.21 ambiance_lifecycle=active -redstoner_version=0.0.0-alpha.11 +redstoner_version=0.0.0-alpha.12 redstoner_lifecycle=active anotherworld_version=0.0.0-alpha.55 anotherworld_lifecycle=active @@ -30,5 +30,5 @@ onlyfun_version=0.0.0-alpha.25 onlyfun_lifecycle=active sanctuary_version=0.0.0-alpha.122 sanctuary_lifecycle=active -pack_version=26.2.0-alpha.219 +pack_version=26.2.0-alpha.220 maven_group=fr.koka99cab.sanctuary26 diff --git a/pack/migrations/26.2.0-alpha.219-storage-terminal-menu-to-alpha.220.json b/pack/migrations/26.2.0-alpha.219-storage-terminal-menu-to-alpha.220.json new file mode 100644 index 0000000..7a8c6e6 --- /dev/null +++ b/pack/migrations/26.2.0-alpha.219-storage-terminal-menu-to-alpha.220.json @@ -0,0 +1,54 @@ +{ + "schema_version": 1, + "source": { + "pack_version": "26.2.0-alpha.219", + "modules": { + "redstoner": "0.0.0-alpha.11" + } + }, + "target": { + "pack_version": "26.2.0-alpha.220", + "modules": { + "redstoner": "0.0.0-alpha.12" + } + }, + "storage_terminal_menu": { + "owner": "redstoner", + "id": "redstoner:storage_terminal", + "menu_type": "redstoner:storage_terminal", + "native_container_menu": true, + "dedicated_close_button": false, + "terminal_slots": 54, + "terminal_slots_reorderable": false, + "quantity_data_words_per_slot": 2, + "minimum_player_inventory_rows": 1, + "maximum_player_inventory_rows": 6, + "inventory_rows_authority": "sanctuary_progression", + "left_click_with_empty_cursor": "take_stack", + "right_click_with_empty_cursor": "take_one", + "click_with_carried_stack": "deposit", + "shift_click_from_terminal": "take_to_unlocked_inventory", + "shift_click_from_player": "deposit", + "deposit_order": "first_discovered_container", + "per_container_order": ["compatible_stacks", "empty_slots"], + "spill_to_next_container_when_required": true, + "strict_item_component_aggregation": true, + "server_authoritative_transfers": true, + "vanilla_menu_synchronization": true, + "legacy_terminal_payloads_removed": true + }, + "compatibility": { + "new_world_required": false, + "save_reset_required": false, + "existing_saves_supported": true, + "redstoner_data_version": 3, + "redstoner_source_network_protocol": 6, + "redstoner_target_network_protocol": 7 + }, + "distribution": { + "pack_release_updated": true, + "packwiz_index_refreshed": true, + "prism_modrinth_index_updated": true, + "shared_client_server_mrpack": true + } +} diff --git a/pack/packwiz/index.toml b/pack/packwiz/index.toml index d4eb802..8f7175e 100644 --- a/pack/packwiz/index.toml +++ b/pack/packwiz/index.toml @@ -60,8 +60,8 @@ file = "mods/ouch-0.0.0-alpha.10.jar" hash = "c414a5b308796a797c6dce9b0337edfd06c536a18d1c746307f58e99e3a6be2c" [[files]] -file = "mods/redstoner-0.0.0-alpha.11.jar" -hash = "753a7b4f8a26a836904099ed034dc36dcb371b87f5b67044940345fdadeb6b33" +file = "mods/redstoner-0.0.0-alpha.12.jar" +hash = "2535d57df6bfdac3444204ee57a351f6f5174d5f2a6067d3bb3a5f096ecae52b" [[files]] file = "mods/sanctuary-0.0.0-alpha.122.jar" diff --git a/pack/packwiz/pack.toml b/pack/packwiz/pack.toml index cf27ee4..40d9d73 100644 --- a/pack/packwiz/pack.toml +++ b/pack/packwiz/pack.toml @@ -1,12 +1,12 @@ name = "Sanctuary 26.2" author = "KOKA99CAB" -version = "26.2.0-alpha.219" +version = "26.2.0-alpha.220" pack-format = "packwiz:1.1.0" [index] file = "index.toml" hash-format = "sha256" -hash = "a694c1327286dca4369aa64dfea7decbc36fedbba77188e7d8d310c08365d415" +hash = "52cb256574fb9e4df7cd05d8029feff7bb737e35253e85c3048a8d50997f3f62" [versions] fabric = "0.19.3" diff --git a/pack/prism/modrinth.index.json b/pack/prism/modrinth.index.json index 20e4692..1d0d8c0 100644 --- a/pack/prism/modrinth.index.json +++ b/pack/prism/modrinth.index.json @@ -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.219", + "versionId": "26.2.0-alpha.220", "files": [ { "path": "mods/fabric-api-0.158.0+26.2.jar", diff --git a/pack/release.json b/pack/release.json index df4d890..66eb07a 100644 --- a/pack/release.json +++ b/pack/release.json @@ -1,6 +1,6 @@ { "schema_version": 1, - "pack_version": "26.2.0-alpha.219", + "pack_version": "26.2.0-alpha.220", "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.219.mrpack", + "primary_file": "sanctuary-26.2.0-alpha.220.mrpack", "shared_client_server_pack": true, "update_owner": "packwiz-installer", "check_on_launch": true, diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/RedStonerMod.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/RedStonerMod.java index fac0dee..f1553e4 100644 --- a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/RedStonerMod.java +++ b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/RedStonerMod.java @@ -3,6 +3,7 @@ package fr.koka99cab.sanctuary26.redstoner; import fr.koka99cab.sanctuary26.redstoner.api.RedStonerApi; import fr.koka99cab.sanctuary26.redstoner.network.RedStonerNetworking; import fr.koka99cab.sanctuary26.redstoner.registry.RedStonerRegistries; +import fr.koka99cab.sanctuary26.redstoner.registry.RedStonerMenus; import fr.koka99cab.sanctuary26.sanctuary.api.server.SanctuaryServerIdentity; import net.fabricmc.api.ModInitializer; import net.minecraft.resources.Identifier; @@ -26,6 +27,7 @@ public final class RedStonerMod implements ModInitializer { public void onInitialize() { RedStonerApi.registerServerIdentityProvider(SanctuaryServerIdentity::get); RedStonerRegistries.initialize(); + RedStonerMenus.initialize(); RedStonerNetworking.initialize(); LOGGER.info("[{}] Computers, Drawer, Particuleur and Storage Terminal ready (data v{}, network v{}).", DISPLAY_NAME, CURRENT_DATA_VERSION, RedStonerNetworking.PROTOCOL_VERSION); diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/block/StorageTerminalBlock.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/block/StorageTerminalBlock.java index ad486db..ed48205 100644 --- a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/block/StorageTerminalBlock.java +++ b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/block/StorageTerminalBlock.java @@ -1,7 +1,7 @@ package fr.koka99cab.sanctuary26.redstoner.block; import com.mojang.serialization.MapCodec; -import fr.koka99cab.sanctuary26.redstoner.network.RedStonerNetworking; +import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalMenu; import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalNetwork; import java.util.Map; import net.minecraft.core.BlockPos; @@ -106,7 +106,7 @@ public final class StorageTerminalBlock extends Block { private static InteractionResult open(Level level, BlockPos pos, Player player) { if (level.isClientSide()) return InteractionResult.SUCCESS; if (player instanceof ServerPlayer serverPlayer) { - RedStonerNetworking.openStorageTerminal(serverPlayer, pos); + StorageTerminalMenu.open(serverPlayer, pos); return InteractionResult.SUCCESS_SERVER; } return InteractionResult.CONSUME; diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/RedStonerClient.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/RedStonerClient.java index c1c5a73..6a623f1 100644 --- a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/RedStonerClient.java +++ b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/RedStonerClient.java @@ -7,17 +7,19 @@ import fr.koka99cab.sanctuary26.redstoner.client.gui.StorageTerminalScreen; import fr.koka99cab.sanctuary26.redstoner.client.renderer.DrawerBlockEntityRenderer; import fr.koka99cab.sanctuary26.redstoner.network.OpenComputerPayload; import fr.koka99cab.sanctuary26.redstoner.network.OpenPersonalComputerPayload; -import fr.koka99cab.sanctuary26.redstoner.network.StorageTerminalSnapshotPayload; +import fr.koka99cab.sanctuary26.redstoner.registry.RedStonerMenus; import fr.koka99cab.sanctuary26.redstoner.registry.RedStonerRegistries; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry; +import net.minecraft.client.gui.screens.MenuScreens; public final class RedStonerClient implements ClientModInitializer { @Override public void onInitializeClient() { BlockEntityRendererRegistry.register(RedStonerRegistries.DRAWER_BLOCK_ENTITY, DrawerBlockEntityRenderer::new); BlockEntityRendererRegistry.register(RedStonerRegistries.LEGACY_DRAWER_BLOCK_ENTITY, DrawerBlockEntityRenderer::new); + MenuScreens.register(RedStonerMenus.STORAGE_TERMINAL, StorageTerminalScreen::new); ClientPlayNetworking.registerGlobalReceiver(OpenComputerPayload.TYPE, (payload, context) -> context.client().execute(() -> context.client().gui.setScreen(new ComputerScreen(payload)))); ClientPlayNetworking.registerGlobalReceiver(OpenPersonalComputerPayload.TYPE, (payload, context) -> @@ -28,15 +30,6 @@ public final class RedStonerClient implements ClientModInitializer { context.client().gui.setScreen(new PersonalComputerScreen(payload)); } })); - ClientPlayNetworking.registerGlobalReceiver(StorageTerminalSnapshotPayload.TYPE, (payload, context) -> - context.client().execute(() -> { - if (context.client().gui.screen() instanceof StorageTerminalScreen screen - && screen.represents(payload)) { - screen.acceptSnapshot(payload); - } else { - context.client().gui.setScreen(new StorageTerminalScreen(payload)); - } - })); RedStonerMod.LOGGER.info("[{}] Client renderers and laboratory screens ready.", RedStonerMod.DISPLAY_NAME); } diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/gui/StorageTerminalScreen.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/gui/StorageTerminalScreen.java index f111525..f9a94a9 100644 --- a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/gui/StorageTerminalScreen.java +++ b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/gui/StorageTerminalScreen.java @@ -1,86 +1,97 @@ package fr.koka99cab.sanctuary26.redstoner.client.gui; -import fr.koka99cab.sanctuary26.redstoner.network.StorageTerminalActionPayload; -import fr.koka99cab.sanctuary26.redstoner.network.StorageTerminalSnapshotPayload; -import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalRules; +import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalMenu; import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalStatus; -import java.util.Locale; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import java.util.ArrayList; +import java.util.List; +import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.input.MouseButtonEvent; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -public final class StorageTerminalScreen extends Screen { - private static final int PANEL_WIDTH = 204; - private static final int PANEL_HEIGHT = 236; - private static final int SLOT_SIZE = 18; - private static final int GRID_X = 8; - private static final int GRID_Y = 20; - private static final int PLAYER_GRID_Y = 152; - private static final int HOTBAR_Y = 210; - private static final int SCROLL_X = 176; - private static final int SCROLL_WIDTH = 8; - private static final int REFRESH_TICKS = 20; - - private StorageTerminalSnapshotPayload snapshot; +/** Vanilla-style terminal surface composed with Sanctuary's dynamic player-inventory panel. */ +public final class StorageTerminalScreen extends AbstractContainerScreen { + private static final Identifier TEXTURE = Identifier.withDefaultNamespace( + "textures/gui/container/generic_54.png"); + private static final int TERMINAL_TOP = 18; + private static final int TERMINAL_HEIGHT = 108; + private static final int SCROLL_X = 171; + private static final int SCROLL_WIDTH = 4; private int requestedPage; - private int refreshCooldown = REFRESH_TICKS; - public StorageTerminalScreen(StorageTerminalSnapshotPayload snapshot) { - super(Component.translatable("screen.redstoner.storage_terminal.title")); - this.snapshot = snapshot; - this.requestedPage = snapshot.page(); - } - - public boolean represents(StorageTerminalSnapshotPayload other) { - return snapshot.pos().equals(other.pos()); - } - - public void acceptSnapshot(StorageTerminalSnapshotPayload refreshed) { - if (!represents(refreshed)) return; - snapshot = refreshed; - requestedPage = refreshed.page(); - refreshCooldown = REFRESH_TICKS; + public StorageTerminalScreen(StorageTerminalMenu menu, Inventory inventory, Component title) { + super(menu, inventory, title, 176, 222); + requestedPage = menu.page(); } @Override protected void init() { - addRenderableWidget(Button.builder(Component.literal("×"), button -> onClose()) - .bounds(panelX() + PANEL_WIDTH - 22, panelY() + 4, 18, 14).build()); + super.init(); + titleLabelX = 8; + titleLabelY = 6; } @Override - public void tick() { - if (--refreshCooldown <= 0) requestPage(requestedPage); + public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float tickDelta) { + super.extractBackground(graphics, mouseX, mouseY, tickDelta); + graphics.blit(RenderPipelines.GUI_TEXTURED, TEXTURE, leftPos, topPos, 0.0F, 0.0F, + imageWidth, imageHeight, 256, 256); + extractScrollBar(graphics); } @Override - public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float tickDelta) { - graphics.fill(0, 0, width, height, 0xCC101010); - int x = panelX(); - int y = panelY(); - graphics.fill(x + 3, y + 3, x + PANEL_WIDTH + 3, y + PANEL_HEIGHT + 3, 0xA0000000); - graphics.fill(x, y, x + PANEL_WIDTH, y + PANEL_HEIGHT, 0xFFC6C6C6); - graphics.outline(x, y, PANEL_WIDTH, PANEL_HEIGHT, 0xFF373737); - graphics.text(font, title, x + 8, y + 7, 0xFF202020, false); + protected void extractLabels(GuiGraphicsExtractor graphics, int mouseX, int mouseY) { + graphics.text(font, title, titleLabelX, titleLabelY, 0xFF404040, false); + Component pageLabel = Component.literal((menu.page() + 1) + "/" + menu.pageCount()); + graphics.text(font, pageLabel, 168 - font.width(pageLabel), titleLabelY, 0xFF404040, false); + if (menu.status() != StorageTerminalStatus.READY) { + graphics.centeredText(font, menu.statusMessage(), imageWidth / 2, 68, 0xFFAA3333); + } + } - if (snapshot.status() == StorageTerminalStatus.READY) { - renderTerminalGrid(graphics, x, y, mouseX, mouseY); - } else { - graphics.centeredText(font, Component.translatable("screen.redstoner.storage_terminal.error." - + snapshot.status().name().toLowerCase(Locale.ROOT)), x + 90, y + 70, 0xFFAA3333); + @Override + protected void extractSlot(GuiGraphicsExtractor graphics, Slot slot, int mouseX, int mouseY) { + super.extractSlot(graphics, slot, mouseX, mouseY); + if (slot.index < StorageTerminalMenu.TERMINAL_SLOT_COUNT && slot.hasItem()) { + int total = menu.totalAt(slot.index); + if (total > 1) { + String label = compactCount(total); + graphics.text(font, label, slot.x + 17 - font.width(label), slot.y + 9, + 0xFFFFFFFF, true); + } + } + } + + @Override + protected List getTooltipFromContainerItem(ItemStack stack) { + List tooltip = new ArrayList<>(super.getTooltipFromContainerItem(stack)); + if (hoveredSlot != null && hoveredSlot.index < StorageTerminalMenu.TERMINAL_SLOT_COUNT) { + int total = menu.totalAt(hoveredSlot.index); + if (total > 0) tooltip.add(Component.literal("×" + total).withStyle(ChatFormatting.GRAY)); + } + return tooltip; + } + + @Override + protected void extractTooltip(GuiGraphicsExtractor graphics, int mouseX, int mouseY) { + super.extractTooltip(graphics, mouseX, mouseY); + if (isHovering(SCROLL_X - 2, TERMINAL_TOP, SCROLL_WIDTH + 4, TERMINAL_HEIGHT, mouseX, mouseY)) { + graphics.setTooltipForNextFrame(font, Component.translatable( + "screen.redstoner.storage_terminal.summary", + menu.page() + 1, menu.pageCount(), menu.containerCount(), menu.totalEntries()), + mouseX, mouseY); } - renderPlayerInventory(graphics, x, y, mouseX, mouseY); - super.extractRenderState(graphics, mouseX, mouseY, tickDelta); } @Override public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) { - if (snapshot.status() == StorageTerminalStatus.READY && scrollY != 0.0D && insidePanel(mouseX, mouseY)) { + if (scrollY != 0.0D && isHovering(7, TERMINAL_TOP, 169, TERMINAL_HEIGHT, mouseX, mouseY)) { requestPage(requestedPage + (scrollY < 0.0D ? 1 : -1)); return true; } @@ -89,151 +100,41 @@ public final class StorageTerminalScreen extends Screen { @Override public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) { - if (super.mouseClicked(event, doubleClick)) return true; - if (snapshot.status() == StorageTerminalStatus.READY) { - int entryIndex = terminalEntryAt(event.x(), event.y()); - if (entryIndex >= 0 && entryIndex < snapshot.entries().size() - && (event.button() == 0 || event.button() == 1)) { - StorageTerminalSnapshotPayload.Entry entry = snapshot.entries().get(entryIndex); - send(event.button() == 1 ? StorageTerminalActionPayload.Action.TAKE_ONE - : StorageTerminalActionPayload.Action.TAKE_STACK, snapshot.page(), entryIndex, -1, entry.stack()); - return true; - } - if (insideScrollBar(event.x(), event.y()) && event.button() == 0) { - double ratio = Math.max(0.0D, Math.min(0.999D, - (event.y() - panelY() - GRID_Y) / (StorageTerminalRules.PAGE_SIZE / 9.0D * SLOT_SIZE))); - requestPage((int) Math.floor(ratio * snapshot.pageCount())); - return true; - } - int playerSlot = playerSlotAt(event.x(), event.y()); - if (playerSlot >= 0 && event.button() == 0 && event.hasShiftDown() && minecraft.player != null) { - ItemStack stack = minecraft.player.getInventory().getItem(playerSlot); - if (!stack.isEmpty()) { - send(StorageTerminalActionPayload.Action.DEPOSIT_SLOT, snapshot.page(), -1, playerSlot, stack); - return true; - } - } + if (event.button() == 0 + && isHovering(SCROLL_X - 2, TERMINAL_TOP, SCROLL_WIDTH + 4, TERMINAL_HEIGHT, + event.x(), event.y())) { + double ratio = Math.clamp((event.y() - topPos - TERMINAL_TOP) / TERMINAL_HEIGHT, + 0.0D, 0.999999D); + requestPage((int) Math.floor(ratio * menu.pageCount())); + return true; } - return false; + return super.mouseClicked(event, doubleClick); } @Override - public boolean isPauseScreen() { - return false; + protected void containerTick() { + requestedPage = menu.page(); } - private void renderTerminalGrid(GuiGraphicsExtractor graphics, int x, int y, int mouseX, int mouseY) { - for (int index = 0; index < StorageTerminalRules.PAGE_SIZE; index++) { - int slotX = x + GRID_X + index % 9 * SLOT_SIZE; - int slotY = y + GRID_Y + index / 9 * SLOT_SIZE; - drawSlot(graphics, slotX, slotY); - if (index >= snapshot.entries().size()) continue; - StorageTerminalSnapshotPayload.Entry entry = snapshot.entries().get(index); - graphics.item(entry.stack(), slotX + 1, slotY + 1); - graphics.itemDecorations(font, entry.stack(), slotX + 1, slotY + 1, compactCount(entry.total())); - if (inside(mouseX, mouseY, slotX, slotY, SLOT_SIZE, SLOT_SIZE)) { - graphics.setTooltipForNextFrame(font, entry.stack(), mouseX, mouseY); - } - } - - int trackX = x + SCROLL_X; - int trackY = y + GRID_Y; - int trackHeight = 6 * SLOT_SIZE; - graphics.fill(trackX, trackY, trackX + SCROLL_WIDTH, trackY + trackHeight, 0xFF575757); - int thumbHeight = snapshot.pageCount() <= 1 ? trackHeight : Math.max(10, trackHeight / snapshot.pageCount()); - int travel = trackHeight - thumbHeight; - int thumbY = trackY + (snapshot.pageCount() <= 1 ? 0 - : Math.round(travel * snapshot.page() / (float) (snapshot.pageCount() - 1))); - graphics.fill(trackX + 1, thumbY + 1, trackX + SCROLL_WIDTH - 1, thumbY + thumbHeight - 1, 0xFFD8D8D8); - graphics.text(font, Component.translatable("screen.redstoner.storage_terminal.summary", - snapshot.page() + 1, snapshot.pageCount(), snapshot.containerCount(), snapshot.totalEntries()), - x + 8, y + 131, 0xFF555555, false); - } - - private void renderPlayerInventory(GuiGraphicsExtractor graphics, int x, int y, int mouseX, int mouseY) { - graphics.text(font, Component.translatable("container.inventory"), x + 8, y + 141, 0xFF202020, false); - if (minecraft.player == null) return; - Inventory inventory = minecraft.player.getInventory(); - for (int row = 0; row < 3; row++) { - for (int column = 0; column < 9; column++) { - int inventorySlot = 9 + row * 9 + column; - drawPlayerSlot(graphics, inventory, inventorySlot, x + GRID_X + column * SLOT_SIZE, - y + PLAYER_GRID_Y + row * SLOT_SIZE, mouseX, mouseY); - } - } - for (int column = 0; column < 9; column++) { - drawPlayerSlot(graphics, inventory, column, x + GRID_X + column * SLOT_SIZE, - y + HOTBAR_Y, mouseX, mouseY); + private void requestPage(int requested) { + int page = Math.clamp(requested, 0, menu.pageCount() - 1); + requestedPage = page; + if (minecraft != null && minecraft.gameMode != null) { + minecraft.gameMode.handleInventoryButtonClick(menu.containerId, + StorageTerminalMenu.PAGE_BUTTON_BASE + page); } } - private void drawPlayerSlot(GuiGraphicsExtractor graphics, Inventory inventory, int inventorySlot, - int x, int y, int mouseX, int mouseY) { - drawSlot(graphics, x, y); - ItemStack stack = inventory.getItem(inventorySlot); - if (stack.isEmpty()) return; - graphics.item(stack, x + 1, y + 1); - graphics.itemDecorations(font, stack, x + 1, y + 1); - if (inside(mouseX, mouseY, x, y, SLOT_SIZE, SLOT_SIZE)) { - graphics.setTooltipForNextFrame(font, stack, mouseX, mouseY); - } - } - - private static void drawSlot(GuiGraphicsExtractor graphics, int x, int y) { - graphics.fill(x, y, x + SLOT_SIZE, y + SLOT_SIZE, 0xFF373737); - graphics.fill(x + 1, y + 1, x + SLOT_SIZE - 1, y + SLOT_SIZE - 1, 0xFF8B8B8B); - } - - private void requestPage(int page) { - requestedPage = Math.max(0, Math.min(snapshot.pageCount() - 1, page)); - refreshCooldown = REFRESH_TICKS; - send(StorageTerminalActionPayload.Action.REQUEST_PAGE, requestedPage, -1, -1, ItemStack.EMPTY); - } - - private void send(StorageTerminalActionPayload.Action action, int page, int entryIndex, - int playerSlot, ItemStack expected) { - if (ClientPlayNetworking.canSend(StorageTerminalActionPayload.TYPE)) { - ClientPlayNetworking.send(new StorageTerminalActionPayload( - snapshot.pos(), action, page, entryIndex, playerSlot, expected)); - } - } - - private int terminalEntryAt(double mouseX, double mouseY) { - int relativeX = (int) mouseX - panelX() - GRID_X; - int relativeY = (int) mouseY - panelY() - GRID_Y; - if (relativeX < 0 || relativeY < 0 || relativeX >= 9 * SLOT_SIZE || relativeY >= 6 * SLOT_SIZE) return -1; - return relativeY / SLOT_SIZE * 9 + relativeX / SLOT_SIZE; - } - - private int playerSlotAt(double mouseX, double mouseY) { - int relativeX = (int) mouseX - panelX() - GRID_X; - if (relativeX < 0 || relativeX >= 9 * SLOT_SIZE) return -1; - int column = relativeX / SLOT_SIZE; - int mainY = (int) mouseY - panelY() - PLAYER_GRID_Y; - if (mainY >= 0 && mainY < 3 * SLOT_SIZE) return 9 + mainY / SLOT_SIZE * 9 + column; - int hotbarY = (int) mouseY - panelY() - HOTBAR_Y; - return hotbarY >= 0 && hotbarY < SLOT_SIZE ? column : -1; - } - - private boolean insideScrollBar(double mouseX, double mouseY) { - return inside(mouseX, mouseY, panelX() + SCROLL_X, panelY() + GRID_Y, - SCROLL_WIDTH, 6 * SLOT_SIZE); - } - - private boolean insidePanel(double mouseX, double mouseY) { - return inside(mouseX, mouseY, panelX(), panelY(), PANEL_WIDTH, PANEL_HEIGHT); - } - - private static boolean inside(double mouseX, double mouseY, int x, int y, int width, int height) { - return mouseX >= x && mouseX < x + width && mouseY >= y && mouseY < y + height; - } - - private int panelX() { - return (width - PANEL_WIDTH) / 2; - } - - private int panelY() { - return (height - PANEL_HEIGHT) / 2; + private void extractScrollBar(GuiGraphicsExtractor graphics) { + int x = leftPos + SCROLL_X; + int y = topPos + TERMINAL_TOP; + graphics.fill(x, y, x + SCROLL_WIDTH, y + TERMINAL_HEIGHT, 0xFF8B8B8B); + int pageCount = menu.pageCount(); + int handleHeight = Math.max(8, TERMINAL_HEIGHT / pageCount); + int travel = TERMINAL_HEIGHT - handleHeight; + int handleY = y + (pageCount <= 1 ? 0 : menu.page() * travel / (pageCount - 1)); + graphics.fill(x, handleY, x + SCROLL_WIDTH, handleY + handleHeight, 0xFFE0E0E0); + graphics.outline(x, y, SCROLL_WIDTH, TERMINAL_HEIGHT, 0xFF373737); } private static String compactCount(int count) { diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/RedStonerNetworking.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/RedStonerNetworking.java index be09538..80d29e6 100644 --- a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/RedStonerNetworking.java +++ b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/RedStonerNetworking.java @@ -4,11 +4,7 @@ import fr.koka99cab.sanctuary26.redstoner.RedStonerMod; import fr.koka99cab.sanctuary26.redstoner.block.entity.ComputerBlockEntity; import fr.koka99cab.sanctuary26.redstoner.block.entity.PersonalComputerBlockEntity; import fr.koka99cab.sanctuary26.redstoner.registry.RedStonerRegistries; -import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalNetwork; -import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalService; import fr.koka99cab.sanctuary26.sanctuary.api.atlas.SanctuaryAtlasLandmarks; -import java.util.List; -import net.minecraft.core.BlockPos; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.server.level.ServerPlayer; @@ -16,7 +12,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.Vec3; public final class RedStonerNetworking { - public static final int PROTOCOL_VERSION = 6; + public static final int PROTOCOL_VERSION = 7; private static boolean initialized; private RedStonerNetworking() { @@ -29,8 +25,6 @@ public final class RedStonerNetworking { initialized = true; PayloadTypeRegistry.clientboundPlay().register(OpenComputerPayload.TYPE, OpenComputerPayload.STREAM_CODEC); PayloadTypeRegistry.clientboundPlay().register(OpenPersonalComputerPayload.TYPE, OpenPersonalComputerPayload.STREAM_CODEC); - PayloadTypeRegistry.clientboundPlay().register(StorageTerminalSnapshotPayload.TYPE, - StorageTerminalSnapshotPayload.STREAM_CODEC); PayloadTypeRegistry.serverboundPlay().register(SaveComputerProgramPayload.TYPE, SaveComputerProgramPayload.STREAM_CODEC); PayloadTypeRegistry.serverboundPlay().register(PlaceAtlasLandmarkPayload.TYPE, PlaceAtlasLandmarkPayload.STREAM_CODEC); PayloadTypeRegistry.serverboundPlay().register(RequestPersonalComputerSnapshotPayload.TYPE, @@ -39,8 +33,6 @@ public final class RedStonerNetworking { AcknowledgePersonalComputerIntroPayload.STREAM_CODEC); PayloadTypeRegistry.serverboundPlay().register(ShutdownPersonalComputerPayload.TYPE, ShutdownPersonalComputerPayload.STREAM_CODEC); - PayloadTypeRegistry.serverboundPlay().register(StorageTerminalActionPayload.TYPE, - StorageTerminalActionPayload.STREAM_CODEC); ServerPlayNetworking.registerGlobalReceiver(SaveComputerProgramPayload.TYPE, (payload, context) -> context.server().execute(() -> saveProgram(context.player(), payload))); ServerPlayNetworking.registerGlobalReceiver(PlaceAtlasLandmarkPayload.TYPE, (payload, context) -> @@ -51,8 +43,6 @@ public final class RedStonerNetworking { context.server().execute(() -> acknowledgePersonalComputerIntro(context.player(), payload))); ServerPlayNetworking.registerGlobalReceiver(ShutdownPersonalComputerPayload.TYPE, (payload, context) -> context.server().execute(() -> shutdownPersonalComputer(context.player(), payload))); - ServerPlayNetworking.registerGlobalReceiver(StorageTerminalActionPayload.TYPE, (payload, context) -> - context.server().execute(() -> storageTerminalAction(context.player(), payload))); RedStonerMod.LOGGER.debug("[{}] Networking contract v{} registered.", RedStonerMod.DISPLAY_NAME, PROTOCOL_VERSION); } @@ -87,23 +77,6 @@ public final class RedStonerNetworking { } } - public static void openStorageTerminal(ServerPlayer player, BlockPos pos) { - sendStorageTerminalSnapshot(player, pos, StorageTerminalService.snapshot(player, pos, 0)); - } - - private static void storageTerminalAction(ServerPlayer player, StorageTerminalActionPayload payload) { - sendStorageTerminalSnapshot(player, payload.pos(), StorageTerminalService.handle(player, payload)); - } - - private static void sendStorageTerminalSnapshot(ServerPlayer player, BlockPos pos, - StorageTerminalNetwork.Snapshot snapshot) { - if (!ServerPlayNetworking.canSend(player, StorageTerminalSnapshotPayload.TYPE)) return; - List entries = snapshot.entries().stream() - .map(entry -> new StorageTerminalSnapshotPayload.Entry(entry.stack(), entry.total())).toList(); - ServerPlayNetworking.send(player, new StorageTerminalSnapshotPayload(pos, snapshot.status(), snapshot.page(), - snapshot.pageCount(), snapshot.containerCount(), snapshot.totalEntries(), entries)); - } - private static void requestPersonalComputerSnapshot(ServerPlayer player, RequestPersonalComputerSnapshotPayload payload) { PersonalComputerBlockEntity computer = validatedPersonalComputer( diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/StorageTerminalActionPayload.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/StorageTerminalActionPayload.java deleted file mode 100644 index 9ea01fc..0000000 --- a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/StorageTerminalActionPayload.java +++ /dev/null @@ -1,56 +0,0 @@ -package fr.koka99cab.sanctuary26.redstoner.network; - -import fr.koka99cab.sanctuary26.redstoner.RedStonerMod; -import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalRules; -import net.minecraft.core.BlockPos; -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.world.item.ItemStack; - -public record StorageTerminalActionPayload(BlockPos pos, Action action, int page, int entryIndex, - int playerSlot, ItemStack expected) implements CustomPacketPayload { - public static final Type TYPE = - new Type<>(RedStonerMod.id("c2s/storage_terminal_action")); - public static final StreamCodec STREAM_CODEC = - StreamCodec.of(StorageTerminalActionPayload::write, StorageTerminalActionPayload::read); - - public StorageTerminalActionPayload { - pos = pos == null ? BlockPos.ZERO : pos.immutable(); - action = action == null ? Action.REQUEST_PAGE : action; - page = Math.max(0, Math.min(StorageTerminalRules.MAX_PAGE_COUNT - 1, page)); - entryIndex = entryIndex >= 0 && entryIndex < StorageTerminalRules.PAGE_SIZE ? entryIndex : -1; - playerSlot = playerSlot >= 0 && playerSlot < StorageTerminalRules.PLAYER_STORAGE_SLOTS ? playerSlot : -1; - expected = expected == null || expected.isEmpty() ? ItemStack.EMPTY : expected.copyWithCount(1); - } - - private static StorageTerminalActionPayload read(RegistryFriendlyByteBuf buffer) { - BlockPos pos = buffer.readBlockPos(); - int ordinal = buffer.readVarInt(); - Action[] values = Action.values(); - Action action = ordinal >= 0 && ordinal < values.length ? values[ordinal] : Action.REQUEST_PAGE; - return new StorageTerminalActionPayload(pos, action, buffer.readVarInt(), buffer.readVarInt(), - buffer.readVarInt(), ItemStack.OPTIONAL_UNTRUSTED_STREAM_CODEC.decode(buffer)); - } - - private static void write(RegistryFriendlyByteBuf buffer, StorageTerminalActionPayload payload) { - buffer.writeBlockPos(payload.pos); - buffer.writeVarInt(payload.action.ordinal()); - buffer.writeVarInt(payload.page); - buffer.writeVarInt(payload.entryIndex); - buffer.writeVarInt(payload.playerSlot); - ItemStack.OPTIONAL_UNTRUSTED_STREAM_CODEC.encode(buffer, payload.expected); - } - - @Override - public Type type() { - return TYPE; - } - - public enum Action { - REQUEST_PAGE, - TAKE_STACK, - TAKE_ONE, - DEPOSIT_SLOT - } -} diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/StorageTerminalSnapshotPayload.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/StorageTerminalSnapshotPayload.java deleted file mode 100644 index 3ecd55a..0000000 --- a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/StorageTerminalSnapshotPayload.java +++ /dev/null @@ -1,80 +0,0 @@ -package fr.koka99cab.sanctuary26.redstoner.network; - -import fr.koka99cab.sanctuary26.redstoner.RedStonerMod; -import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalRules; -import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalStatus; -import java.util.ArrayList; -import java.util.List; -import net.minecraft.core.BlockPos; -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.world.item.ItemStack; - -public record StorageTerminalSnapshotPayload(BlockPos pos, StorageTerminalStatus status, int page, - int pageCount, int containerCount, int totalEntries, List entries) implements CustomPacketPayload { - public static final Type TYPE = - new Type<>(RedStonerMod.id("s2c/storage_terminal_snapshot")); - public static final StreamCodec STREAM_CODEC = - StreamCodec.of(StorageTerminalSnapshotPayload::write, StorageTerminalSnapshotPayload::read); - - public StorageTerminalSnapshotPayload { - pos = pos == null ? BlockPos.ZERO : pos.immutable(); - status = status == null ? StorageTerminalStatus.INVALID_TERMINAL : status; - pageCount = Math.max(1, Math.min(StorageTerminalRules.MAX_PAGE_COUNT, pageCount)); - page = Math.max(0, Math.min(pageCount - 1, page)); - containerCount = Math.max(0, Math.min(StorageTerminalRules.MAX_CONTAINERS, containerCount)); - totalEntries = Math.max(0, Math.min(StorageTerminalRules.MAX_ENTRIES, totalEntries)); - entries = entries == null ? List.of() : List.copyOf(entries.stream() - .limit(StorageTerminalRules.PAGE_SIZE).toList()); - } - - private static StorageTerminalSnapshotPayload read(RegistryFriendlyByteBuf buffer) { - BlockPos pos = buffer.readBlockPos(); - StorageTerminalStatus status = status(buffer.readVarInt()); - int page = buffer.readVarInt(); - int pageCount = buffer.readVarInt(); - int containerCount = buffer.readVarInt(); - int totalEntries = buffer.readVarInt(); - int size = buffer.readVarInt(); - if (size < 0 || size > StorageTerminalRules.PAGE_SIZE) { - throw new IllegalArgumentException("Storage terminal page exceeds " + StorageTerminalRules.PAGE_SIZE); - } - List entries = new ArrayList<>(size); - for (int index = 0; index < size; index++) { - entries.add(new Entry(ItemStack.OPTIONAL_UNTRUSTED_STREAM_CODEC.decode(buffer), buffer.readVarInt())); - } - return new StorageTerminalSnapshotPayload(pos, status, page, pageCount, containerCount, totalEntries, entries); - } - - private static void write(RegistryFriendlyByteBuf buffer, StorageTerminalSnapshotPayload payload) { - buffer.writeBlockPos(payload.pos); - buffer.writeVarInt(payload.status.ordinal()); - buffer.writeVarInt(payload.page); - buffer.writeVarInt(payload.pageCount); - buffer.writeVarInt(payload.containerCount); - buffer.writeVarInt(payload.totalEntries); - buffer.writeVarInt(payload.entries.size()); - for (Entry entry : payload.entries) { - ItemStack.OPTIONAL_UNTRUSTED_STREAM_CODEC.encode(buffer, entry.stack); - buffer.writeVarInt(entry.total); - } - } - - private static StorageTerminalStatus status(int ordinal) { - StorageTerminalStatus[] values = StorageTerminalStatus.values(); - return values[Math.max(0, Math.min(values.length - 1, ordinal))]; - } - - @Override - public Type type() { - return TYPE; - } - - public record Entry(ItemStack stack, int total) { - public Entry { - stack = stack == null || stack.isEmpty() ? ItemStack.EMPTY : stack.copyWithCount(1); - total = stack.isEmpty() ? 0 : Math.max(1, total); - } - } -} diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/registry/RedStonerMenus.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/registry/RedStonerMenus.java new file mode 100644 index 0000000..b110b40 --- /dev/null +++ b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/registry/RedStonerMenus.java @@ -0,0 +1,23 @@ +package fr.koka99cab.sanctuary26.redstoner.registry; + +import fr.koka99cab.sanctuary26.redstoner.RedStonerMod; +import fr.koka99cab.sanctuary26.redstoner.storage.StorageTerminalMenu; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.flag.FeatureFlags; +import net.minecraft.world.inventory.MenuType; + +public final class RedStonerMenus { + public static final MenuType STORAGE_TERMINAL = Registry.register( + BuiltInRegistries.MENU, + RedStonerMod.id("storage_terminal"), + new MenuType<>(StorageTerminalMenu::new, FeatureFlags.VANILLA_SET) + ); + + private RedStonerMenus() { + } + + public static void initialize() { + RedStonerMod.LOGGER.debug("[{}] Storage-terminal menu registered.", RedStonerMod.DISPLAY_NAME); + } +} diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalInventory.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalInventory.java index e915000..7f3f112 100644 --- a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalInventory.java +++ b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalInventory.java @@ -27,7 +27,10 @@ public final class StorageTerminalInventory { return List.copyOf(result); } - /** Inserts into compatible existing stacks first, then into empty slots. Mutates {@code source}. */ + /** + * Fills each container in discovery order, preferring its compatible stacks before its empty slots. + * Mutates {@code source} and only spills into the next container when the current one cannot accept more. + */ public static int insert(List containers, ItemStack source) { if (source == null || source.isEmpty()) return 0; int before = source.getCount(); @@ -43,8 +46,6 @@ public final class StorageTerminalInventory { source.shrink(moved); container.setChanged(); } - } - for (Container container : containers) { for (int slot = 0; slot < container.getContainerSize() && !source.isEmpty(); slot++) { if (!container.getItem(slot).isEmpty() || !container.canPlaceItem(slot, source)) continue; int limit = Math.min(container.getMaxStackSize(source), source.getMaxStackSize()); diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalMenu.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalMenu.java new file mode 100644 index 0000000..887dc95 --- /dev/null +++ b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalMenu.java @@ -0,0 +1,298 @@ +package fr.koka99cab.sanctuary26.redstoner.storage; + +import fr.koka99cab.sanctuary26.redstoner.registry.RedStonerMenus; +import fr.koka99cab.sanctuary26.redstoner.registry.RedStonerRegistries; +import fr.koka99cab.sanctuary26.sanctuary.api.inventory.SanctuaryPlayerInventoryView; +import java.util.List; +import java.util.Locale; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.SimpleMenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.ContainerInput; +import net.minecraft.world.inventory.SimpleContainerData; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; + +/** A server-authoritative, read-only aggregate view over the connected physical storage. */ +public final class StorageTerminalMenu extends AbstractContainerMenu { + public static final int TERMINAL_SLOT_COUNT = StorageTerminalRules.PAGE_SIZE; + public static final int PAGE_BUTTON_BASE = 10; + private static final int PLAYER_INVENTORY_Y = 140; + private static final int REFRESH_INTERVAL = 20; + private static final double MAX_DISTANCE_SQUARED = 64.0D; + private static final int STATUS_DATA = 0; + private static final int PAGE_DATA = 1; + private static final int PAGE_COUNT_DATA = 2; + private static final int CONTAINER_COUNT_DATA = 3; + private static final int TOTAL_ENTRIES_DATA = 4; + private static final int TOTALS_DATA = 5; + private static final int WORDS_PER_TOTAL = 2; + private static final int DATA_COUNT = TOTALS_DATA + TERMINAL_SLOT_COUNT * WORDS_PER_TOTAL; + + private final SimpleContainer display = new SimpleContainer(TERMINAL_SLOT_COUNT); + private final ContainerData data; + private final ServerPlayer serverPlayer; + private final BlockPos terminalPos; + private StorageTerminalNetwork.Discovery discovery = + StorageTerminalNetwork.Discovery.error(StorageTerminalStatus.INVALID_TERMINAL); + private List entries = List.of(); + private int refreshCooldown = REFRESH_INTERVAL; + + public StorageTerminalMenu(int containerId, Inventory inventory) { + this(containerId, inventory, new SimpleContainerData(DATA_COUNT), null, null); + } + + public StorageTerminalMenu(int containerId, Inventory inventory, ServerPlayer player, BlockPos pos) { + this(containerId, inventory, new SimpleContainerData(DATA_COUNT), player, pos.immutable()); + refresh(0); + } + + private StorageTerminalMenu(int containerId, Inventory inventory, ContainerData data, + ServerPlayer serverPlayer, BlockPos terminalPos) { + super(RedStonerMenus.STORAGE_TERMINAL, containerId); + checkContainerDataCount(data, DATA_COUNT); + this.data = data; + this.serverPlayer = serverPlayer; + this.terminalPos = terminalPos; + for (int row = 0; row < 6; row++) { + for (int column = 0; column < 9; column++) { + int slot = column + row * 9; + addSlot(new TerminalDisplaySlot(display, slot, 8 + column * 18, 18 + row * 18)); + } + } + addStandardInventorySlots(inventory, 8, PLAYER_INVENTORY_Y); + addDataSlots(data); + } + + public static void open(ServerPlayer player, BlockPos pos) { + if (player.distanceToSqr(Vec3.atCenterOf(pos)) > MAX_DISTANCE_SQUARED) return; + player.openMenu(new SimpleMenuProvider( + (containerId, inventory, ignored) -> new StorageTerminalMenu(containerId, inventory, player, pos), + Component.translatable("screen.redstoner.storage_terminal.title"))); + } + + public StorageTerminalStatus status() { + StorageTerminalStatus[] values = StorageTerminalStatus.values(); + return values[Math.clamp(data.get(STATUS_DATA), 0, values.length - 1)]; + } + + public int page() { + return Math.max(0, data.get(PAGE_DATA)); + } + + public int pageCount() { + return Math.max(1, data.get(PAGE_COUNT_DATA)); + } + + public int containerCount() { + return Math.max(0, data.get(CONTAINER_COUNT_DATA)); + } + + public int totalEntries() { + return Math.max(0, data.get(TOTAL_ENTRIES_DATA)); + } + + public int totalAt(int slot) { + if (slot < 0 || slot >= TERMINAL_SLOT_COUNT) return 0; + int base = TOTALS_DATA + slot * WORDS_PER_TOTAL; + return StorageTerminalRules.totalFromWords(data.get(base), data.get(base + 1)); + } + + public Component statusMessage() { + return Component.translatable("screen.redstoner.storage_terminal.error." + + status().name().toLowerCase(Locale.ROOT)); + } + + @Override + public boolean clickMenuButton(Player player, int buttonId) { + if (serverPlayer == null || player != serverPlayer || !stillValid(player)) return false; + int requestedPage = buttonId - PAGE_BUTTON_BASE; + if (requestedPage < 0 || requestedPage >= StorageTerminalRules.MAX_PAGE_COUNT) return false; + refresh(requestedPage); + broadcastChanges(); + return true; + } + + @Override + public void clicked(int slotId, int button, ContainerInput input, Player player) { + if (slotId >= 0 && slotId < TERMINAL_SLOT_COUNT) { + if (input == ContainerInput.QUICK_MOVE) { + if (serverPlayer != null) quickMoveStack(player, slotId); + return; + } + if (input == ContainerInput.PICKUP && (button == 0 || button == 1)) { + if (serverPlayer != null && player == serverPlayer && stillValid(player)) { + if (getCarried().isEmpty()) takeToCarried(slotId, button == 1); + else depositCarried(button == 1); + } + return; + } + return; + } + super.clicked(slotId, button, input, player); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + if (serverPlayer == null || player != serverPlayer || !stillValid(player) + || index < 0 || index >= slots.size()) return ItemStack.EMPTY; + if (index < TERMINAL_SLOT_COUNT) return takeIntoPlayer(index); + + Slot sourceSlot = slots.get(index); + if (!sourceSlot.hasItem() || !sourceSlot.mayPickup(player)) return ItemStack.EMPTY; + if (!ready()) return ItemStack.EMPTY; + ItemStack source = sourceSlot.getItem(); + ItemStack original = source.copy(); + int moved = StorageTerminalInventory.insert(discovery.inventoryContainers(), source); + if (moved <= 0) return ItemStack.EMPTY; + if (source.isEmpty()) sourceSlot.setByPlayer(ItemStack.EMPTY); + else sourceSlot.setChanged(); + sourceSlot.onTake(player, source); + refresh(page()); + broadcastChanges(); + return original; + } + + @Override + public boolean stillValid(Player player) { + if (serverPlayer == null || terminalPos == null) return true; + return player == serverPlayer + && player.distanceToSqr(Vec3.atCenterOf(terminalPos)) <= MAX_DISTANCE_SQUARED + && player.level().getBlockState(terminalPos).is(RedStonerRegistries.STORAGE_TERMINAL); + } + + @Override + public void broadcastChanges() { + if (serverPlayer != null && --refreshCooldown <= 0) refresh(page()); + super.broadcastChanges(); + } + + @Override + public boolean canDragTo(Slot slot) { + return !(slot instanceof TerminalDisplaySlot) && super.canDragTo(slot); + } + + @Override + public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { + return !(slot instanceof TerminalDisplaySlot) && super.canTakeItemForPickAll(stack, slot); + } + + private void refresh(int requestedPage) { + if (serverPlayer == null || terminalPos == null) return; + discovery = StorageTerminalNetwork.discover(serverPlayer, terminalPos); + StorageTerminalNetwork.Snapshot snapshot = StorageTerminalNetwork.snapshot(discovery, requestedPage); + entries = snapshot.entries(); + data.set(STATUS_DATA, snapshot.status().ordinal()); + data.set(PAGE_DATA, snapshot.page()); + data.set(PAGE_COUNT_DATA, snapshot.pageCount()); + data.set(CONTAINER_COUNT_DATA, snapshot.containerCount()); + data.set(TOTAL_ENTRIES_DATA, snapshot.totalEntries()); + for (int slot = 0; slot < TERMINAL_SLOT_COUNT; slot++) { + StorageTerminalInventory.Entry entry = slot < entries.size() ? entries.get(slot) : null; + display.setItem(slot, entry == null ? ItemStack.EMPTY : entry.stack().copyWithCount(1)); + int total = entry == null ? 0 : entry.total(); + int base = TOTALS_DATA + slot * WORDS_PER_TOTAL; + data.set(base, StorageTerminalRules.totalLowWord(total)); + data.set(base + 1, StorageTerminalRules.totalHighWord(total)); + } + refreshCooldown = REFRESH_INTERVAL; + } + + private boolean ready() { + if (serverPlayer == null || terminalPos == null) return false; + discovery = StorageTerminalNetwork.discover(serverPlayer, terminalPos); + return discovery.status() == StorageTerminalStatus.READY; + } + + private void takeToCarried(int slot, boolean single) { + if (!ready() || slot >= entries.size()) return; + StorageTerminalInventory.Entry entry = entries.get(slot); + int requested = single ? 1 : entry.stack().getMaxStackSize(); + ItemStack extracted = StorageTerminalInventory.take(discovery.inventoryContainers(), entry.stack(), + Math.min(entry.total(), requested)); + if (extracted.isEmpty()) return; + setCarried(extracted); + refresh(page()); + broadcastChanges(); + } + + private void depositCarried(boolean single) { + if (!ready()) return; + ItemStack carried = getCarried(); + int offeredCount = single ? 1 : carried.getCount(); + ItemStack offered = carried.copyWithCount(offeredCount); + int moved = StorageTerminalInventory.insert(discovery.inventoryContainers(), offered); + if (moved <= 0) return; + carried.shrink(moved); + if (carried.isEmpty()) setCarried(ItemStack.EMPTY); + refresh(page()); + broadcastChanges(); + } + + private ItemStack takeIntoPlayer(int slot) { + if (!ready() || slot >= entries.size()) return ItemStack.EMPTY; + StorageTerminalInventory.Entry entry = entries.get(slot); + int requested = Math.min(entry.total(), entry.stack().getMaxStackSize()); + ItemStack extracted = StorageTerminalInventory.take(discovery.inventoryContainers(), entry.stack(), requested); + if (extracted.isEmpty()) return ItemStack.EMPTY; + ItemStack original = extracted.copy(); + int inserted = insertPlayer(serverPlayer, extracted); + if (!extracted.isEmpty()) StorageTerminalInventory.insert(discovery.inventoryContainers(), extracted); + if (inserted <= 0) return ItemStack.EMPTY; + refresh(page()); + broadcastChanges(); + return original.copyWithCount(inserted); + } + + private static int insertPlayer(ServerPlayer player, ItemStack source) { + int before = source.getCount(); + var slots = SanctuaryPlayerInventoryView.unlockedRows(player); + for (var slot : slots) { + if (source.isEmpty()) break; + ItemStack target = slot.stack(); + if (target.isEmpty() || !ItemStack.isSameItemSameComponents(target, source) + || !slot.container().canPlaceItem(slot.slot(), source)) continue; + int limit = Math.min(target.getMaxStackSize(), slot.container().getMaxStackSize(source)); + int moved = Math.min(source.getCount(), Math.max(0, limit - target.getCount())); + if (moved <= 0) continue; + target.grow(moved); + source.shrink(moved); + slot.markChanged(); + } + for (var slot : slots) { + if (source.isEmpty()) break; + if (!slot.stack().isEmpty() || !slot.container().canPlaceItem(slot.slot(), source)) continue; + int limit = Math.min(source.getMaxStackSize(), slot.container().getMaxStackSize(source)); + int moved = Math.min(source.getCount(), Math.max(0, limit)); + if (moved <= 0) continue; + slot.container().setItem(slot.slot(), source.copyWithCount(moved)); + source.shrink(moved); + slot.markChanged(); + } + return before - source.getCount(); + } + + private static final class TerminalDisplaySlot extends Slot { + private TerminalDisplaySlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + + @Override + public boolean mayPlace(ItemStack stack) { + return false; + } + + @Override + public boolean mayPickup(Player player) { + return hasItem(); + } + } +} diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalRules.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalRules.java index 4185f3e..4352764 100644 --- a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalRules.java +++ b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalRules.java @@ -6,7 +6,6 @@ public final class StorageTerminalRules { public static final int SLOTS_PER_CONTAINER = 27; public static final int MAX_ENTRIES = MAX_CONTAINERS * SLOTS_PER_CONTAINER; public static final int MAX_PAGE_COUNT = MAX_ENTRIES / PAGE_SIZE; - public static final int PLAYER_STORAGE_SLOTS = 36; private StorageTerminalRules() { } @@ -23,4 +22,16 @@ public final class StorageTerminalRules { public static int pageStart(int requestedPage, int entryCount) { return clampPage(requestedPage, entryCount) * PAGE_SIZE; } + + public static int totalLowWord(int total) { + return Math.max(0, total) & 0xFFFF; + } + + public static int totalHighWord(int total) { + return Math.max(0, total) >>> 16; + } + + public static int totalFromWords(int low, int high) { + return (low & 0xFFFF) | (high & 0xFFFF) << 16; + } } diff --git a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalService.java b/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalService.java deleted file mode 100644 index 532f5bc..0000000 --- a/redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalService.java +++ /dev/null @@ -1,109 +0,0 @@ -package fr.koka99cab.sanctuary26.redstoner.storage; - -import fr.koka99cab.sanctuary26.redstoner.network.StorageTerminalActionPayload; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.Vec3; - -public final class StorageTerminalService { - private static final double MAX_DISTANCE_SQUARED = 64.0D; - - private StorageTerminalService() { - } - - public static StorageTerminalNetwork.Snapshot snapshot(ServerPlayer player, BlockPos pos, int page) { - if (player.distanceToSqr(Vec3.atCenterOf(pos)) > MAX_DISTANCE_SQUARED) { - return StorageTerminalNetwork.snapshot( - StorageTerminalNetwork.Discovery.error(StorageTerminalStatus.INVALID_TERMINAL), 0); - } - return StorageTerminalNetwork.snapshot(StorageTerminalNetwork.discover(player, pos), page); - } - - public static StorageTerminalNetwork.Snapshot handle(ServerPlayer player, StorageTerminalActionPayload payload) { - if (player.distanceToSqr(Vec3.atCenterOf(payload.pos())) > MAX_DISTANCE_SQUARED) { - return StorageTerminalNetwork.snapshot( - StorageTerminalNetwork.Discovery.error(StorageTerminalStatus.INVALID_TERMINAL), 0); - } - StorageTerminalNetwork.Discovery discovery = StorageTerminalNetwork.discover(player, payload.pos()); - StorageTerminalNetwork.Snapshot before = StorageTerminalNetwork.snapshot(discovery, payload.page()); - if (before.status() != StorageTerminalStatus.READY - || payload.action() == StorageTerminalActionPayload.Action.REQUEST_PAGE) return before; - - boolean changed = switch (payload.action()) { - case TAKE_STACK -> take(player, discovery, before, payload, false); - case TAKE_ONE -> take(player, discovery, before, payload, true); - case DEPOSIT_SLOT -> deposit(player, discovery, payload); - case REQUEST_PAGE -> false; - }; - if (changed) { - player.getInventory().setChanged(); - player.containerMenu.broadcastChanges(); - player.inventoryMenu.broadcastChanges(); - } - return StorageTerminalNetwork.snapshot(discovery, before.page()); - } - - private static boolean take(ServerPlayer player, StorageTerminalNetwork.Discovery discovery, - StorageTerminalNetwork.Snapshot snapshot, StorageTerminalActionPayload payload, boolean single) { - if (payload.entryIndex() < 0 || payload.entryIndex() >= snapshot.entries().size()) return false; - StorageTerminalInventory.Entry entry = snapshot.entries().get(payload.entryIndex()); - if (payload.expected().isEmpty() - || !ItemStack.isSameItemSameComponents(entry.stack(), payload.expected())) return false; - int capacity = playerCapacity(player.getInventory(), entry.stack()); - int requested = single ? 1 : entry.stack().getMaxStackSize(); - int amount = Math.min(entry.total(), Math.min(capacity, requested)); - if (amount <= 0) return false; - ItemStack extracted = StorageTerminalInventory.take(discovery.inventoryContainers(), entry.stack(), amount); - if (extracted.isEmpty()) return false; - int inserted = insertPlayer(player.getInventory(), extracted); - if (!extracted.isEmpty()) StorageTerminalInventory.insert(discovery.inventoryContainers(), extracted); - return inserted > 0; - } - - private static boolean deposit(ServerPlayer player, StorageTerminalNetwork.Discovery discovery, - StorageTerminalActionPayload payload) { - int slot = payload.playerSlot(); - if (slot < 0 || slot >= StorageTerminalRules.PLAYER_STORAGE_SLOTS) return false; - Inventory inventory = player.getInventory(); - ItemStack source = inventory.getItem(slot); - if (source.isEmpty() || payload.expected().isEmpty() - || !ItemStack.isSameItemSameComponents(source, payload.expected())) return false; - int inserted = StorageTerminalInventory.insert(discovery.inventoryContainers(), source); - if (source.isEmpty()) inventory.setItem(slot, ItemStack.EMPTY); - return inserted > 0; - } - - private static int playerCapacity(Inventory inventory, ItemStack expected) { - long capacity = 0L; - for (int slot = 0; slot < StorageTerminalRules.PLAYER_STORAGE_SLOTS; slot++) { - ItemStack stack = inventory.getItem(slot); - if (stack.isEmpty()) capacity += expected.getMaxStackSize(); - else if (ItemStack.isSameItemSameComponents(stack, expected)) { - capacity += Math.max(0, stack.getMaxStackSize() - stack.getCount()); - } - } - return (int) Math.min(Integer.MAX_VALUE, capacity); - } - - /** Inserts into the 36 survival storage slots and mutates {@code source}. */ - private static int insertPlayer(Inventory inventory, ItemStack source) { - int before = source.getCount(); - for (int slot = 0; slot < StorageTerminalRules.PLAYER_STORAGE_SLOTS && !source.isEmpty(); slot++) { - ItemStack target = inventory.getItem(slot); - if (target.isEmpty() || !ItemStack.isSameItemSameComponents(target, source)) continue; - int moved = Math.min(source.getCount(), Math.max(0, target.getMaxStackSize() - target.getCount())); - if (moved <= 0) continue; - target.grow(moved); - source.shrink(moved); - } - for (int slot = 0; slot < StorageTerminalRules.PLAYER_STORAGE_SLOTS && !source.isEmpty(); slot++) { - if (!inventory.getItem(slot).isEmpty()) continue; - int moved = Math.min(source.getCount(), source.getMaxStackSize()); - inventory.setItem(slot, source.copyWithCount(moved)); - source.shrink(moved); - } - return before - source.getCount(); - } -} diff --git a/redstoner/src/main/resources/fabric.mod.json b/redstoner/src/main/resources/fabric.mod.json index d1ca570..2623956 100644 --- a/redstoner/src/main/resources/fabric.mod.json +++ b/redstoner/src/main/resources/fabric.mod.json @@ -31,7 +31,7 @@ "system_type": "gameplay-system", "namespace": "redstoner", "data_version": 3, - "network_protocol": 6, + "network_protocol": 7, "lifecycle": "${lifecycle}", "pack_version": "${pack_version}", "descriptions": { diff --git a/redstoner/src/test/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalSmoke.java b/redstoner/src/test/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalSmoke.java index a903de6..e8a9863 100644 --- a/redstoner/src/test/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalSmoke.java +++ b/redstoner/src/test/java/fr/koka99cab/sanctuary26/redstoner/storage/StorageTerminalSmoke.java @@ -1,6 +1,5 @@ package fr.koka99cab.sanctuary26.redstoner.storage; -import fr.koka99cab.sanctuary26.redstoner.network.StorageTerminalActionPayload; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -25,7 +24,6 @@ public final class StorageTerminalSmoke { Bootstrap.bootStrap(); verifyTopology(); verifyPagination(); - verifyActionBounds(); verifyAggregationAndTransfers(); } @@ -54,17 +52,12 @@ public final class StorageTerminalSmoke { require(StorageTerminalRules.pageCount(54) == 1, "A full visible page overflowed"); require(StorageTerminalRules.pageCount(55) == 2, "The second page did not open"); require(StorageTerminalRules.clampPage(999, 55) == 1, "A hostile page index was not clamped"); - } - - private static void verifyActionBounds() { - StorageTerminalActionPayload hostile = new StorageTerminalActionPayload(BlockPos.ZERO, - StorageTerminalActionPayload.Action.DEPOSIT_SLOT, -5, 999, 999, ItemStack.EMPTY); - require(hostile.page() == 0 && hostile.entryIndex() == -1 && hostile.playerSlot() == -1, - "Hostile terminal action indexes were mapped to valid slots"); - StorageTerminalActionPayload missingAction = new StorageTerminalActionPayload( - BlockPos.ZERO, null, 0, -1, -1, ItemStack.EMPTY); - require(missingAction.action() == StorageTerminalActionPayload.Action.REQUEST_PAGE, - "A missing terminal action did not fall back to a read-only request"); + int networkMaximum = StorageTerminalRules.MAX_CONTAINERS + * StorageTerminalRules.SLOTS_PER_CONTAINER * 64; + require(StorageTerminalRules.totalFromWords( + (short) StorageTerminalRules.totalLowWord(networkMaximum), + (short) StorageTerminalRules.totalHighWord(networkMaximum)) == networkMaximum, + "A large aggregated quantity was truncated by menu data synchronization"); } private static void verifyAggregationAndTransfers() { @@ -83,6 +76,14 @@ public final class StorageTerminalSmoke { require(first.getItem(0).getCount() == 64 && first.getItem(1).getCount() == 6, "Terminal deposit did not fill matching stacks before empty slots"); + SimpleContainer earliest = new SimpleContainer(1); + SimpleContainer laterMatch = new SimpleContainer(1); + laterMatch.setItem(0, new ItemStack(cobblestone, 60)); + ItemStack orderedDeposit = new ItemStack(cobblestone, 10); + StorageTerminalInventory.insert(List.of(earliest, laterMatch), orderedDeposit); + require(earliest.getItem(0).getCount() == 10 && laterMatch.getItem(0).getCount() == 60, + "Terminal deposit skipped the first available physical container"); + List entries = StorageTerminalInventory.aggregate(List.of(first, second)); require(entries.size() == 2, "Items with distinct components were merged"); StorageTerminalInventory.Entry plain = entries.stream() -- 2.54.0 From b5dab3b5f6d7507d84d7639fc063d56558d009ef Mon Sep 17 00:00:00 2001 From: koka Date: Sun, 30 Aug 2026 07:07:36 +0200 Subject: [PATCH 3/3] chore(release): prepare alpha.221 native audio --- CHANGELOG.md | 10 + README.md | 6 +- ambiance/WHITE_DISC.md | 2 +- .../client/audio/LavaplayerAudioStream.java | 2 +- build.gradle | 391 +++++++++++------- gradle.properties | 2 +- ...0-white-disc-native-rate-to-alpha.221.json | 46 +++ pack/packwiz/index.toml | 22 +- pack/packwiz/pack.toml | 4 +- pack/prism/modrinth.index.json | 2 +- pack/release.json | 4 +- 11 files changed, 330 insertions(+), 161 deletions(-) create mode 100644 pack/migrations/26.2.0-alpha.220-white-disc-native-rate-to-alpha.221.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 3620a5b..92de6f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,16 @@ 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.221` + +Module modifié : **Ambiance `0.0.0-alpha.22`**. Les neuf autres modules conservent leur version issue de l'alpha.220. + +- corrige la cause réelle du disque blanc ralenti et trop grave : la piste AAC YouTube reste décodée en stéréo native à 48 kHz, puis chaque paire gauche/droite est explicitement moyennée en un échantillon mono positionnel ; +- supprime la compensation OpenAL approximative à `4/3` et restitue la musique à sa hauteur et sa vitesse originales avec une hauteur `1.0` ; +- conserve un flux PCM mono signé 16 bits little-endian pour l'audio positionnel du jukebox, sans silence ajouté ni changement de durée ; +- ajoute un test déterministe du downmix stéréo et valide le lien signalé sur quatre secondes : 4 000 ms de source donnent 4 000 ms de PCM à 48 kHz ; +- conserve les données Ambiance v2, le protocole réseau 6, les IDs et les sauvegardes existantes ; aucun nouveau monde ni réinitialisation n'est nécessaire. + ## `26.2.0-alpha.220` Module modifié : **Red-Stoner `0.0.0-alpha.12`**. Les neuf autres modules conservent leur version issue de l'alpha.219. diff --git a/README.md b/README.md index 3def907..7ca97dd 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,19 @@ 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.220`**. Cette release distribue Red-Stoner **`0.0.0-alpha.12`** ; les neuf autres modules conservent leur version issue de l'alpha.219. +Version courante du pack distribué : **`26.2.0-alpha.221`**. Cette release distribue Ambiance **`0.0.0-alpha.22`** ; les neuf autres modules conservent leur version issue de l'alpha.220. 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.221 corrige la cause réelle du disque blanc ralenti et trop grave : Ambiance décode désormais la source AAC en stéréo native à 48 kHz, puis moyenne explicitement chaque paire gauche/droite vers le flux mono positionnel de Minecraft. OpenAL reste à sa hauteur normale `1.0`, sans compensation artificielle ni changement de durée. + L’alpha.220 transforme le terminal de stockage en véritable menu de conteneur, sans bouton de fermeture propriétaire. Les clics gauche/droit et shift-clic permettent maintenant de retirer ou déposer des piles depuis toutes les rangées d’inventaire débloquées par Sanctuary, jusqu’à six ; la grille agrégée reste non réorganisable et remplit chaque coffre ou baril dans l’ordre de découverte avant de passer au suivant. 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.217 tentait de compenser la hauteur trop grave du disque blanc par un facteur OpenAL de `4/3`. Cette compensation est retirée par l’alpha.221, qui corrige directement la conversion stéréo vers mono. 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. diff --git a/ambiance/WHITE_DISC.md b/ambiance/WHITE_DISC.md index a1e7a44..810be9c 100644 --- a/ambiance/WHITE_DISC.md +++ b/ambiance/WHITE_DISC.md @@ -16,7 +16,7 @@ jukebox vanilla. libre ; il est envoyé uniquement aux clients qui suivent le chunk et annoncent le canal ; - chaque client ouvre lui-même la source YouTube, refuse les directs et les vidéos de plus de trente minutes, et limite les lectures simultanées à quatre ; -- la source AAC stéréo est décodée à 48 kHz puis convertie explicitement en PCM mono 16 bits +- la source AAC stéréo est décodée à 48 kHz (48 000 Hz) puis convertie explicitement en PCM mono 16 bits little-endian, échantillon gauche/droite par échantillon gauche/droite, afin de conserver la vitesse et la hauteur originales tout en restant positionnelle ; - OpenAL lit ce PCM à sa hauteur native `1.0` sur le canal `RECORDS`, avec une atténuation à diff --git a/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java b/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java index 488d48a..4b8ea8b 100644 --- a/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java +++ b/ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java @@ -9,7 +9,7 @@ import java.util.concurrent.TimeoutException; import javax.sound.sampled.AudioFormat; import net.minecraft.client.sounds.AudioStream; -/** Adapts bounded mono PCM frames from Lavaplayer to Minecraft's streaming OpenAL channel. */ +/** Downmixes bounded stereo PCM frames from Lavaplayer for Minecraft's mono OpenAL stream. */ final class LavaplayerAudioStream implements AudioStream { static final int SAMPLE_RATE = 48_000; static final int SOURCE_CHANNELS = 2; diff --git a/build.gradle b/build.gradle index f29b5e9..daa0b40 100644 --- a/build.gradle +++ b/build.gradle @@ -3437,7 +3437,7 @@ 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || 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 @@ -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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.anotherworld_version != "0.0.0-alpha.55" || rootProject.redstoner_version != "0.0.0-alpha.12" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version @@ -4275,7 +4275,7 @@ 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.onlyfun_version != "0.0.0-alpha.25" || rootProject.sanctuary_version != "0.0.0-alpha.122" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version @@ -4320,7 +4320,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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || 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" @@ -4369,7 +4369,7 @@ 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.onlyfun_version != "0.0.0-alpha.25" || rootProject.sanctuary_version != "0.0.0-alpha.122" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version @@ -4415,7 +4415,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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || migration.source?.pack_version != "26.2.0-alpha.195" || migration.target?.pack_version != "26.2.0-alpha.196" || migration.target?.modules != [ @@ -4433,10 +4433,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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" - || !packwiz.contains('version = "26.2.0-alpha.220"')) { + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" + || !packwiz.contains('version = "26.2.0-alpha.221"')) { throw new GradleException("The alpha.196 culinary, mailbox and grapple release contract is incomplete") } } @@ -4461,7 +4461,7 @@ 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.itsalive_version != "0.0.0-alpha.36" || rootProject.sanctuary_version != "0.0.0-alpha.122" || migration.source?.pack_version != "26.2.0-alpha.196" @@ -4481,10 +4481,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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" - || !packwiz.contains('version = "26.2.0-alpha.220"')) { + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" + || !packwiz.contains('version = "26.2.0-alpha.221"')) { throw new GradleException("The alpha.197 quest-request and cauldron-batch release contract is incomplete") } } @@ -4511,7 +4511,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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || 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" @@ -4530,10 +4530,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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" - || !packwiz.contains('version = "26.2.0-alpha.220"') + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" + || !packwiz.contains('version = "26.2.0-alpha.221"') || !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.36.jar"')) { throw new GradleException("The alpha.198 fermentation barrel release contract is incomplete") } @@ -4561,7 +4561,7 @@ 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.itsalive_version != "0.0.0-alpha.36" || rootProject.sanctuary_version != "0.0.0-alpha.122" || migration.source?.pack_version != "26.2.0-alpha.198" @@ -4575,10 +4575,10 @@ 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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" - || !packwiz.contains('version = "26.2.0-alpha.220"') + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" + || !packwiz.contains('version = "26.2.0-alpha.221"') || !packwizIndex.contains('file = "mods/itsalive-0.0.0-alpha.36.jar"') || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.122.jar"')) { throw new GradleException("The alpha.199 quest-request contract release is incomplete") @@ -4616,8 +4616,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.220" - || rootProject.ambiance_version != "0.0.0-alpha.21" + if (rootProject.pack_version != "26.2.0-alpha.221" + || rootProject.ambiance_version != "0.0.0-alpha.22" || 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"] @@ -4650,11 +4650,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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" - || !packwiz.contains('version = "26.2.0-alpha.220"') - || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"') + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" + || !packwiz.contains('version = "26.2.0-alpha.221"') + || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.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") } @@ -4682,7 +4682,7 @@ 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || 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" @@ -4697,10 +4697,10 @@ 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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" - || !packwiz.contains('version = "26.2.0-alpha.220"') + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" + || !packwiz.contains('version = "26.2.0-alpha.221"') || !packwizIndex.contains('file = "mods/sanctuary-0.0.0-alpha.122.jar"')) { throw new GradleException("The alpha.201 quest-request escrow release is incomplete") } @@ -4736,7 +4736,7 @@ 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.anotherworld_version != "0.0.0-alpha.55" || rootProject.itsalive_version != "0.0.0-alpha.36" || rootProject.iliketomoveit_version != "0.0.0-alpha.16" @@ -4776,10 +4776,10 @@ 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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" - || !packwiz.contains('version = "26.2.0-alpha.220"') + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" + || !packwiz.contains('version = "26.2.0-alpha.221"') || !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.16.jar"') @@ -4896,7 +4896,7 @@ 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.anotherworld_version != "0.0.0-alpha.55" || rootProject.sanctuary_version != "0.0.0-alpha.122" || migration.schema_version != 1 @@ -5088,7 +5088,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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || 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"] @@ -5106,9 +5106,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.220.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwiz.contains('version = "26.2.0-alpha.221"') || !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 @@ -5134,7 +5134,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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || 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"] @@ -5160,9 +5160,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.220.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwiz.contains('version = "26.2.0-alpha.221"') || !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 @@ -5188,7 +5188,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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || 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"] @@ -5217,9 +5217,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.220.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwiz.contains('version = "26.2.0-alpha.221"') || !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 @@ -5246,7 +5246,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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || 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"] @@ -5269,9 +5269,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.220.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwiz.contains('version = "26.2.0-alpha.221"') || !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 @@ -5298,7 +5298,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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || 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"] @@ -5328,9 +5328,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.220.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwiz.contains('version = "26.2.0-alpha.221"') || !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 @@ -5386,9 +5386,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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.itsalive_version != "0.0.0-alpha.36" - || rootProject.ambiance_version != "0.0.0-alpha.21" + || rootProject.ambiance_version != "0.0.0-alpha.22" || migration.issue != 35 || migration.source?.fabric_id != "canaplia" || migration.source?.version != "2.0.0" @@ -5638,8 +5638,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.220" - || rootProject.ambiance_version != "0.0.0-alpha.21" + if (rootProject.pack_version != "26.2.0-alpha.221" + || rootProject.ambiance_version != "0.0.0-alpha.22" || 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" @@ -5686,10 +5686,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.220.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.220"') - || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"') + || !packwiz.contains('version = "26.2.0-alpha.221"') + || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.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"') @@ -5739,7 +5739,7 @@ tasks.register("verifyAlpha210Release") { iliketomoveit: "0.0.0-alpha.15", itsalive: "0.0.0-alpha.35"] def currentModules = [ - ambiance: "0.0.0-alpha.21", + ambiance: "0.0.0-alpha.22", sanctuary: "0.0.0-alpha.122", onlyfun: "0.0.0-alpha.25", ouch: "0.0.0-alpha.10", @@ -5756,7 +5756,7 @@ 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.sanctuary_version != "0.0.0-alpha.122" || rootProject.onlyfun_version != "0.0.0-alpha.25" || rootProject.iliketomoveit_version != currentModules.iliketomoveit @@ -5802,10 +5802,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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" - || !packwiz.contains('version = "26.2.0-alpha.220"') + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" + || !packwiz.contains('version = "26.2.0-alpha.221"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || jeiFiles.size() != 1 @@ -5854,7 +5854,7 @@ tasks.register("verifyAlpha211Release") { def currentModules = expectedTarget + [ sanctuary: "0.0.0-alpha.122", onlyfun: "0.0.0-alpha.25", - ambiance: "0.0.0-alpha.21", + ambiance: "0.0.0-alpha.22", iliketomoveit: "0.0.0-alpha.16"] def workspaceModules = currentModules def expectedDataVersions = [ambiance: 2, itsalive: 3, onlyfun: 2, ouch: 1, sanctuary: 11] @@ -5881,7 +5881,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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || workspaceModules.any { id, version -> rootProject.property("${id}_version") != version } || migration.source?.pack_version != "26.2.0-alpha.210" || migration.source?.modules != expectedSource @@ -5909,9 +5909,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.220.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwiz.contains('version = "26.2.0-alpha.221"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || prism.files?.size() != 5 @@ -5919,7 +5919,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.220`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { throw new GradleException("The alpha.211 Abjection and gameplay-polish release is incomplete") } } @@ -5953,7 +5953,7 @@ 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || 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"] @@ -5975,16 +5975,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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" || prism.files?.size() != 5 || jeiFiles.size() != 1 - || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwiz.contains('version = "26.2.0-alpha.221"') || !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.220`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { throw new GradleException("The alpha.212 Black Market startup-fix release is incomplete") } } @@ -6018,8 +6018,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.220" - || rootProject.ambiance_version != "0.0.0-alpha.21" + if (rootProject.pack_version != "26.2.0-alpha.221" + || rootProject.ambiance_version != "0.0.0-alpha.22" || 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" @@ -6042,16 +6042,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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" || prism.files?.size() != 5 || jeiFiles.size() != 1 - || !packwiz.contains('version = "26.2.0-alpha.220"') - || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"') + || !packwiz.contains('version = "26.2.0-alpha.221"') + || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.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.220`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { throw new GradleException("The alpha.213 Ambiance startup-fix release is incomplete") } } @@ -6086,8 +6086,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.220" - || rootProject.ambiance_version != "0.0.0-alpha.21" + if (rootProject.pack_version != "26.2.0-alpha.221" + || rootProject.ambiance_version != "0.0.0-alpha.22" || 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" @@ -6115,16 +6115,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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.220"') - || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"') + || !packwiz.contains('version = "26.2.0-alpha.221"') + || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.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.220`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { throw new GradleException("The alpha.214 white-disc solo synchronization release is incomplete") } } @@ -6165,8 +6165,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.220" - || rootProject.ambiance_version != "0.0.0-alpha.21" + if (rootProject.pack_version != "26.2.0-alpha.221" + || rootProject.ambiance_version != "0.0.0-alpha.22" || 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" @@ -6205,16 +6205,16 @@ tasks.register("verifyAlpha215Release") { || !playbackSmoke.contains("https://www.youtube.com/watch?v=Ue5ZBe-GzSM") || !playbackSmoke.contains("stream.paddedSilenceBytes() != 0L") || !playbackSmoke.contains("stream.decodedTimelineMillis() != 4_000L") - || release.pack_version != "26.2.0-alpha.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.220"') - || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"') + || !packwiz.contains('version = "26.2.0-alpha.221"') + || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.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.220`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { throw new GradleException("The alpha.215 resilient white-disc playback release is incomplete") } } @@ -6259,8 +6259,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.220" - || rootProject.ambiance_version != "0.0.0-alpha.21" + if (rootProject.pack_version != "26.2.0-alpha.221" + || rootProject.ambiance_version != "0.0.0-alpha.22" || 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" @@ -6290,27 +6290,29 @@ tasks.register("verifyAlpha216Release") { || manifest.custom?.sanctuary26?.data_version != 2 || manifest.custom?.sanctuary26?.network_protocol != 6 || !ambianceBuild.contains('tasks.register("whiteDiscStreamSmoke"') - || !audioPlayer.contains("PLAYBACK_PITCH = 4.0F / 3.0F") + || !audioPlayer.contains("PLAYBACK_PITCH = 1.0F") || !audioStream.contains("SAMPLE_RATE = 48_000") || !audioStream.contains("INITIAL_FRAME_WAIT_MILLIS = 2_000L") || !audioStream.contains("CONTINUATION_FRAME_WAIT_MILLIS = 250L") || !audioStream.contains("player.provide(waitMillis, TimeUnit.MILLISECONDS)") || !audioStream.contains("new AudioFormat(SAMPLE_RATE, 16, 1, true, false)") + || !audioStream.contains("SOURCE_CHANNELS = 2") + || !audioStream.contains("downmixStereoFrame(frame.getData())") || !streamSmoke.contains("FRAMES_PER_SECOND") || !streamSmoke.contains("PCM frames were not read with bounded waits") || !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.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.220"') - || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"') + || !packwiz.contains('version = "26.2.0-alpha.221"') + || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.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.220`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { throw new GradleException("The alpha.216 white-disc audio-quality release is incomplete") } } @@ -6345,8 +6347,8 @@ tasks.register("verifyAlpha217Release") { "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.220" - || rootProject.ambiance_version != "0.0.0-alpha.21" + if (rootProject.pack_version != "26.2.0-alpha.221" + || rootProject.ambiance_version != "0.0.0-alpha.22" || 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" @@ -6373,19 +6375,19 @@ tasks.register("verifyAlpha217Release") { || 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.contains("PLAYBACK_PITCH = 1.0F") || audioPlayer.count("channel.setPitch(PLAYBACK_PITCH)") != 2 - || !streamSmoke.contains("WhiteDiscAudioPlayer.PLAYBACK_PITCH - 4.0F / 3.0F") - || release.pack_version != "26.2.0-alpha.220" - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" - || prism.versionId != "26.2.0-alpha.220" + || !streamSmoke.contains("WhiteDiscAudioPlayer.PLAYBACK_PITCH - 1.0F") + || release.pack_version != "26.2.0-alpha.221" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != "26.2.0-alpha.221" || prism.files?.size() != 5 - || !packwiz.contains('version = "26.2.0-alpha.220"') - || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"') + || !packwiz.contains('version = "26.2.0-alpha.221"') + || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.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.220`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { throw new GradleException("The alpha.217 white-disc pitch release is incomplete") } } @@ -6433,14 +6435,14 @@ tasks.register("verifyAlpha218Release") { def targetModules = [ redstoner: "0.0.0-alpha.11", onlyfun: "0.0.0-alpha.25", sanctuary: "0.0.0-alpha.121"] def currentModules = targetModules + [redstoner: "0.0.0-alpha.12", - sanctuary: "0.0.0-alpha.122", iliketomoveit: "0.0.0-alpha.16", ambiance: "0.0.0-alpha.21"] + sanctuary: "0.0.0-alpha.122", iliketomoveit: "0.0.0-alpha.16", ambiance: "0.0.0-alpha.22"] 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.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || currentModules.any { id, version -> rootProject.property("${id}_version") != version } || migration.source?.pack_version != "26.2.0-alpha.217" || migration.source?.modules != sourceModules @@ -6473,13 +6475,13 @@ tasks.register("verifyAlpha218Release") { || !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.220.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwiz.contains('version = "26.2.0-alpha.221"') || requiredJars.any { !packwizIndex.contains(it) } || obsoleteJars.any { packwizIndex.contains(it) } || !changelog.contains("## `26.2.0-alpha.218`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { throw new GradleException("The alpha.218 Storage Terminal release is incomplete") } } @@ -6523,18 +6525,23 @@ tasks.register("verifyAlpha219Release") { 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 -> + def currentModules = targetModules + [ambiance: "0.0.0-alpha.22"] + def requiredJars = currentModules.collect { id, version -> "file = \"mods/${id}-${version}.jar\"" } def obsoleteJars = sourceModules.collect { id, version -> "file = \"mods/${id}-${version}.jar\"" + } + targetModules.findAll { id, version -> + currentModules[id] != version + }.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.220" - || targetModules.any { id, version -> rootProject.property("${id}_version") != version } + if (rootProject.pack_version != "26.2.0-alpha.221" + || currentModules.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" @@ -6565,15 +6572,15 @@ tasks.register("verifyAlpha219Release") { || 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.220.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" || prism.versionId != rootProject.pack_version || prism.files.any { it.path.toLowerCase().contains("golden-days") } - || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwiz.contains('version = "26.2.0-alpha.221"') || 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.220`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { throw new GradleException("The alpha.219 finite Alpha/Indev release is incomplete") } } @@ -6612,7 +6619,7 @@ tasks.register("verifyAlpha220Release") { "redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/client/gui/StorageTerminalScreen.java").text def networking = file( "redstoner/src/main/java/fr/koka99cab/sanctuary26/redstoner/network/RedStonerNetworking.java").text - if (rootProject.pack_version != "26.2.0-alpha.220" + if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.redstoner_version != "0.0.0-alpha.12" || migration.source?.pack_version != "26.2.0-alpha.219" || migration.source?.modules != [redstoner: "0.0.0-alpha.11"] @@ -6653,18 +6660,121 @@ tasks.register("verifyAlpha220Release") { || networking.contains("storage_terminal_snapshot") || networking.contains("storage_terminal_action") || release.pack_version != rootProject.pack_version - || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.220.mrpack" + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" || prism.versionId != rootProject.pack_version - || !packwiz.contains('version = "26.2.0-alpha.220"') + || !packwiz.contains('version = "26.2.0-alpha.221"') || !packwizIndex.contains('file = "mods/redstoner-0.0.0-alpha.12.jar"') || packwizIndex.contains('file = "mods/redstoner-0.0.0-alpha.11.jar"') || !changelog.contains("## `26.2.0-alpha.220`") - || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.220`**")) { + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { throw new GradleException("The alpha.220 Storage Terminal menu release is incomplete") } } } +tasks.register("verifyAlpha221Release") { + group = "verification" + description = "Checks the Sanctuary 26.2.0-alpha.221 native-rate white-disc release." + inputs.file(file("pack/migrations/26.2.0-alpha.220-white-disc-native-rate-to-alpha.221.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/WHITE_DISC.md")) + inputs.file(file("ambiance/build.gradle")) + 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/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java")) + inputs.file(file( + "ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStreamSmoke.java")) + inputs.file(file( + "ambiance/src/test/java/fr/koka99cab/sanctuary26/ambiance/client/audio/WhiteDiscPlaybackSmoke.java")) + doLast { + def migration = new JsonSlurper().parse(file( + "pack/migrations/26.2.0-alpha.220-white-disc-native-rate-to-alpha.221.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 whiteDiscDocumentation = file("ambiance/WHITE_DISC.md").text + def ambianceBuild = file("ambiance/build.gradle").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 audioStream = file( + "ambiance/src/main/java/fr/koka99cab/sanctuary26/ambiance/client/audio/LavaplayerAudioStream.java").text + def streamSmoke = file( + "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 + def contract = migration.white_disc_native_rate + if (rootProject.pack_version != "26.2.0-alpha.221" + || rootProject.ambiance_version != "0.0.0-alpha.22" + || migration.source?.pack_version != "26.2.0-alpha.220" + || migration.source?.modules != [ambiance: "0.0.0-alpha.21"] + || migration.target?.pack_version != "26.2.0-alpha.221" + || migration.target?.modules != [ambiance: "0.0.0-alpha.22"] + || contract?.owner != "ambiance" + || contract?.reference_video_id != "Ue5ZBe-GzSM" + || contract?.source_format != "MP4_AAC_LC" + || contract?.decoded_sample_rate_hz != 48_000 + || contract?.decoded_source_channels != 2 + || contract?.openal_output_channels != 1 + || contract?.sample_size_bits != 16 + || contract?.byte_order != "little_endian" + || contract?.stereo_to_mono != "average_left_right_per_sample" + || contract?.openal_pitch != 1.0 + || contract?.decoded_timeline_millis != 4_000 + || contract?.openal_timeline_millis != 4_000 + || contract?.padded_silence_bytes != 0 + || contract?.positional_audio_preserved != true + || contract?.previous_pitch_compensation_removed != true + || 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 + || !ambianceBuild.contains('tasks.register("whiteDiscStreamSmoke"') + || !ambianceBuild.contains('tasks.register("whiteDiscPlaybackSmoke"') + || !audioPlayer.contains("PLAYBACK_PITCH = 1.0F") + || audioPlayer.count("channel.setPitch(PLAYBACK_PITCH)") != 2 + || !audioPlayer.contains("new Pcm16AudioDataFormat(LavaplayerAudioStream.SOURCE_CHANNELS,") + || !audioStream.contains("SOURCE_CHANNELS = 2") + || !audioStream.contains("FRAME_SAMPLES = 960") + || !audioStream.contains("new AudioFormat(SAMPLE_RATE, 16, 1, true, false)") + || !audioStream.contains("downmixStereoFrame(frame.getData())") + || !audioStream.contains("short mixed = (short) (((int) left + right) / SOURCE_CHANNELS)") + || !streamSmoke.contains("WhiteDiscAudioPlayer.PLAYBACK_PITCH - 1.0F") + || !streamSmoke.contains("Stereo PCM was not downmixed in sample order") + || !playbackSmoke.contains("stream.decodedTimelineMillis() != 4_000L") + || !playbackSmoke.contains("PCM cadence: 100%% speed") + || !whiteDiscDocumentation.contains("48 000 Hz") + || release.pack_version != rootProject.pack_version + || release.modrinth?.primary_file != "sanctuary-26.2.0-alpha.221.mrpack" + || prism.versionId != rootProject.pack_version + || !packwiz.contains('version = "26.2.0-alpha.221"') + || !packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.22.jar"') + || packwizIndex.contains('file = "mods/ambiance-0.0.0-alpha.21.jar"') + || !changelog.contains("## `26.2.0-alpha.221`") + || !readme.contains("Version courante du pack distribué : **`26.2.0-alpha.221`**")) { + throw new GradleException("The alpha.221 native-rate white-disc release is incomplete") + } + } +} + tasks.named("verifyWorkspace") { dependsOn tasks.named("verifyAlpha213Release") dependsOn tasks.named("verifyAlpha214Release") @@ -6674,6 +6784,7 @@ tasks.named("verifyWorkspace") { dependsOn tasks.named("verifyAlpha218Release") dependsOn tasks.named("verifyAlpha219Release") dependsOn tasks.named("verifyAlpha220Release") + dependsOn tasks.named("verifyAlpha221Release") } tasks.named("check") { diff --git a/gradle.properties b/gradle.properties index c6a2dc1..4347b3c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,5 +30,5 @@ onlyfun_version=0.0.0-alpha.25 onlyfun_lifecycle=active sanctuary_version=0.0.0-alpha.122 sanctuary_lifecycle=active -pack_version=26.2.0-alpha.220 +pack_version=26.2.0-alpha.221 maven_group=fr.koka99cab.sanctuary26 diff --git a/pack/migrations/26.2.0-alpha.220-white-disc-native-rate-to-alpha.221.json b/pack/migrations/26.2.0-alpha.220-white-disc-native-rate-to-alpha.221.json new file mode 100644 index 0000000..1ceb633 --- /dev/null +++ b/pack/migrations/26.2.0-alpha.220-white-disc-native-rate-to-alpha.221.json @@ -0,0 +1,46 @@ +{ + "schema_version": 1, + "source": { + "pack_version": "26.2.0-alpha.220", + "modules": { + "ambiance": "0.0.0-alpha.21" + } + }, + "target": { + "pack_version": "26.2.0-alpha.221", + "modules": { + "ambiance": "0.0.0-alpha.22" + } + }, + "white_disc_native_rate": { + "owner": "ambiance", + "reference_video_id": "Ue5ZBe-GzSM", + "source_format": "MP4_AAC_LC", + "decoded_sample_rate_hz": 48000, + "decoded_source_channels": 2, + "openal_output_channels": 1, + "sample_size_bits": 16, + "byte_order": "little_endian", + "stereo_to_mono": "average_left_right_per_sample", + "openal_pitch": 1.0, + "decoded_timeline_millis": 4000, + "openal_timeline_millis": 4000, + "padded_silence_bytes": 0, + "positional_audio_preserved": true, + "previous_pitch_compensation_removed": true + }, + "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 + } +} diff --git a/pack/packwiz/index.toml b/pack/packwiz/index.toml index 8f7175e..4ffb219 100644 --- a/pack/packwiz/index.toml +++ b/pack/packwiz/index.toml @@ -13,16 +13,16 @@ file = "instance-icon.png" hash = "41f4f4c88c71d0a23446d5014f7407d55ad477441847099cad24492b032335a0" [[files]] -file = "mods/ambiance-0.0.0-alpha.21.jar" -hash = "c9dfd6ed13d1fdd2277e62d9bd2faa18c008d621bbcf8ef605736eefc3378663" +file = "mods/ambiance-0.0.0-alpha.22.jar" +hash = "4d5c31315c436c716a48e7d563fd179be2f39951c24bf4641f83a05a24323a3e" [[files]] file = "mods/anotherworld-0.0.0-alpha.55.jar" -hash = "0137f9a8109438c659c7a126ecde2e28982e063ee95f1991603a9ea81bbe7501" +hash = "7fbe2ac0d2ece62285aa8277ff92284760f2ccfd6d08159015661978bd0cde9a" [[files]] file = "mods/events-0.0.0-alpha.0.jar" -hash = "3a666f7b7bdb9cbf7181eff3e49455768ac76905a482577990fdc1eb018e78d7" +hash = "cbf8d47fb82ca06c438b75fd72f805acc9813dffc6168d6786d54644ef8bb387" [[files]] file = "mods/fabric-api.pw.toml" @@ -31,7 +31,7 @@ metafile = true [[files]] file = "mods/iliketomoveit-0.0.0-alpha.16.jar" -hash = "f42ed4fe37cbf3422e3b2493db562e82da3f2ba04568cea6ae304862e64e54df" +hash = "26156014813bfa4384194ac0f20395b6df590a5bc29cd91a32114ced988bbaf3" [[files]] file = "mods/iris.pw.toml" @@ -40,7 +40,7 @@ metafile = true [[files]] file = "mods/itsalive-0.0.0-alpha.36.jar" -hash = "71c9d893fd0862610f203b854d1af19e0e6e4b2bc9e06f6da38d057e23a54ebd" +hash = "5673ab7d605f2f1d18d807f0939f90ecedc13c892d03991fd60f7d02d74f9404" [[files]] file = "mods/jei.pw.toml" @@ -49,23 +49,23 @@ metafile = true [[files]] file = "mods/masterkey-0.0.0-alpha.8.jar" -hash = "75ae764c2b86d2f4479f576d9a1cd8272c1979d754069277052ef11064fabbda" +hash = "202b159fd04b7447cda7fa9f7360693106927904819e834956ab46f6e07f658e" [[files]] file = "mods/onlyfun-0.0.0-alpha.25.jar" -hash = "69cca044dd3cd3fbbd6d9d45706a502ec17689c040521524eac3aa20ab93bf5f" +hash = "6551d75cb3cb7be220b2aa6033d4eb533fa28a39ee88d66bbb0c40244c08c259" [[files]] file = "mods/ouch-0.0.0-alpha.10.jar" -hash = "c414a5b308796a797c6dce9b0337edfd06c536a18d1c746307f58e99e3a6be2c" +hash = "0c2e0e2ef7f6c944d0b6d5609c42431a0a31f1d92087c3b5c28b67f76795d8cf" [[files]] file = "mods/redstoner-0.0.0-alpha.12.jar" -hash = "2535d57df6bfdac3444204ee57a351f6f5174d5f2a6067d3bb3a5f096ecae52b" +hash = "fee65e8d865f918ec8174b7a808762658ed91b566af590d99a3448f9d237175a" [[files]] file = "mods/sanctuary-0.0.0-alpha.122.jar" -hash = "b4ab04b167c50d412af791ccadf838ebcb0443303e05864c9940e02ec3cc0d40" +hash = "9183652d13fd3c15663ca645f96f2a70026cb4d3a82f62e92fc3c72aea72d589" [[files]] file = "mods/simple-voice-chat.pw.toml" diff --git a/pack/packwiz/pack.toml b/pack/packwiz/pack.toml index 40d9d73..f03f11d 100644 --- a/pack/packwiz/pack.toml +++ b/pack/packwiz/pack.toml @@ -1,12 +1,12 @@ name = "Sanctuary 26.2" author = "KOKA99CAB" -version = "26.2.0-alpha.220" +version = "26.2.0-alpha.221" pack-format = "packwiz:1.1.0" [index] file = "index.toml" hash-format = "sha256" -hash = "52cb256574fb9e4df7cd05d8029feff7bb737e35253e85c3048a8d50997f3f62" +hash = "60e8342eef216dd225488fe4225a28c9b9940858642cbfc8025541affd150ab0" [versions] fabric = "0.19.3" diff --git a/pack/prism/modrinth.index.json b/pack/prism/modrinth.index.json index 1d0d8c0..59f830d 100644 --- a/pack/prism/modrinth.index.json +++ b/pack/prism/modrinth.index.json @@ -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.220", + "versionId": "26.2.0-alpha.221", "files": [ { "path": "mods/fabric-api-0.158.0+26.2.jar", diff --git a/pack/release.json b/pack/release.json index 66eb07a..c848346 100644 --- a/pack/release.json +++ b/pack/release.json @@ -1,6 +1,6 @@ { "schema_version": 1, - "pack_version": "26.2.0-alpha.220", + "pack_version": "26.2.0-alpha.221", "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.220.mrpack", + "primary_file": "sanctuary-26.2.0-alpha.221.mrpack", "shared_client_server_pack": true, "update_owner": "packwiz-installer", "check_on_launch": true, -- 2.54.0