diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3bb9971 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space + +[*.{java}] +indent_size = 4 diff --git a/.gitignore b/.gitignore index b870e48..f407000 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,6 @@ run/logs run/schematics run/server run/downloads/log.json +run/command_history.txt +run/world/ +run/world*/ diff --git a/AUDIT_NEOFORGE.md b/AUDIT_NEOFORGE.md new file mode 100644 index 0000000..38ada36 --- /dev/null +++ b/AUDIT_NEOFORGE.md @@ -0,0 +1,413 @@ +# Audit de code — Migration Forge → NeoForge (CreateNuclearNeoForge) + +Document de suivi vivant. À mettre à jour au fur et à mesure que les points listés sont traités. +Périmètre : intégralité de `src/main/java` (207 fichiers, ~19 500 lignes), à l'exclusion des ressources/datagen JSON. +Rappel du cadre : le mod est **en cours de migration** de Forge vers NeoForge 1.21.1. Les usages de patterns Forge qui fonctionnent correctement et ne sont pas explicitement temporaires ne sont **pas** listés comme problème. Les nouvelles fonctionnalités propres à NeoForge 1.21.1 non encore adoptées ne sont **pas** considérées comme un manque. + +Légende priorité : 🔴 Critique · 🟠 Important · 🟡 Moyen · 🟢 Faible + +--- + +## Sommaire + +1. [Bugs fonctionnels critiques découverts pendant l'audit](#0-bugs-fonctionnels-critiques-découverts-pendant-laudit) +2. [Dead Code](#1-dead-code) +3. [Commentaires et Javadocs](#2-commentaires-et-javadocs) +4. [Duplications](#3-duplications) +5. [Migration Forge → NeoForge](#4-migration-forge--neoforge) +6. [Nettoyage](#5-nettoyage) +7. [Refactorisations](#6-refactorisations) +8. [Tableau de priorités global](#7-tableau-de-priorités-global) + +--- + +## 0. Bugs de logique indépendants de la migration + +Le mod étant encore en migration, une bonne partie du code manquant/commenté relevé dans ce rapport (ex. `ReactorAlarmManager`, `ReactorSummaryDisplaySource`, cf. §4) reflète simplement un travail inachevé et n'a **pas** été classée ici — ces cas sont traités dans la section [4. Migration Forge → NeoForge](#4-migration-forge--neoforge) et [1. Dead Code](#1-dead-code) comme du code à terminer, pas comme des anomalies isolées. + +En revanche, les points ci-dessous sont de **vraies erreurs de logique** (inversion de paramètres, copier-coller fautif, condition inversée) qui ne s'expliquent pas par du code manquant côté migration : ils resteraient des bugs même une fois la migration terminée, et méritent donc un traitement indépendant du planning de migration. + +| # | Fichier:ligne | Problème | Priorité | +|---|---|---|---| +| B1 | `content/multiblock/bluePrintItem/ReactorBluePrintItemScreen.java:56-65,71-73` | Les comptes de barres uranium/graphite sont inversés et un `+3` magique est ajouté lors de l'appel à `sendValueUpdate`, puis `sendValueUpdate` renvoie `countCooledRod` deux fois au lieu de `countFuelRod` pour le dernier paramètre : le comptage des barres envoyé au serveur est corrompu. | 🔴 | +| B2 | `content/radiation/capability/RadiationCapability.java:220-223` | Dans `applyEffects`, la branche `radiationLevel3` et la branche `else` utilisent toutes deux `amplifierLevel2.get()` (copier-coller) : il manque un `amplifierLevel3`, l'amplificateur d'effet plafonne au niveau 2 quel que soit le niveau réel de radiation. | 🟠 | +| B3 | `content/multiblock/controller/manager/ReactorInputFluidManager.java:129-130,148-149` | `int tank = h.getTanks(); h.getFluidInTank(tank);` utilise le *nombre* de tanks comme *index* (valides : `0..getTanks()-1`) → accès systématiquement hors bornes. | 🟠 | +| B4 | `lib/multiblock/manager/MultiBlockCache.java:22-24` | `isCached()` a une sémantique inversée : `return cachedResult == null` renvoie `true` quand **rien n'est en cache**. (Classe par ailleurs non utilisée, cf. §1.) | 🟡 | +| B5 | `content/multiblock/controller/ReactorControllerBlockEntity.java:489-491` | `isEmptyConfiguredPattern()` retourne `!configuredPattern.isEmpty()` — le nom est l'inverse exact du comportement. Fonctionne car l'appelant (`tick()`) compense, mais piège de maintenance. | 🟠 | + +### Code manquant/inachevé lié à un travail en cours (à titre indicatif, non compté comme bug) + +Ces trois cas ont une logique entièrement commentée ou un comportement neutralisé, mais rien n'indique que ce soit lié à la migration Forge→NeoForge spécifiquement (plutôt une fonctionnalité en cours de développement) — ils sont donc listés dans les sections thématiques appropriées plutôt qu'ici : `ReactorAlarmManager.clearInvalid()/getBlocksPosition()` (§1.6, purge/récupération des alarmes non finalisée), `ReactorSummaryDisplaySource` (§1.6, alimentation du résumé du réacteur non finalisée — provoque une exception tant que ce n'est pas terminé), `IrradiatedCatRelaxOnOwnerGoal.canUse()` (§1, comportement du chat jamais terminé). + +--- + +## 1. Dead Code + +### 1.1 Classes inutilisées + +| Fichier | Détail | Priorité | +|---|---|---| +| `lib/multiblock/manager/MultiBlockManager.java` | Jamais référencée hors du fichier ; remplacée de facto par `MultiBlockManagerBeta`. | 🟠 | +| `lib/multiblock/manager/RegisteredMultiBlockPattern.java` | Utilisée uniquement par `MultiBlockManager`, donc morte par transitivité. | 🟡 | +| `lib/multiblock/manager/MultiBlockCache.java` | Jamais instanciée nulle part (voir aussi bug B7). | 🟠 | +| `lib/multiblock/impl/IBetterPattern.java` | Jamais utilisée ; stub cassé (`matches` → toujours `false`, `matchesWithResult` → toujours `null`, `construct` → no-op). | 🟠 | +| `foundation/block/EventTriggerBlock.java` | Seul point d'enregistrement (`CNBlocks.java:636-640`) commenté ; classe jamais instanciée en jeu. | 🟡 | +| `content/contraptions/irradiated/wolf/IrradiatedWoldCollarLayer.java` | Jamais instanciée/enregistrée ; `render()` a un corps vide ; nom mal orthographié (« Wold » au lieu de « Wolf »). | 🟠 | +| `foundation/mixin/client/RadiationHeartMixing.java` | Classe entière encapsulée dans un commentaire bloc, non listée dans `createnuclear.neoforge.mixins.json` (qui ne référence que `BaseFireBlockMixin`) : totalement inactive. | 🟠 | +| `foundation/events/possible code` | Fichier **sans extension `.java`**, donc jamais compilé mais versionné dans le repo. Contient du code Forge legacy (`net.minecraftforge.*`) et un `HudOverlayRegistry` fictif basé sur `ServiceLoader`. Brouillon oublié. | 🔴 | +| `content/multiblock/pattern/ReactorPattern.java` (`VerifyPattern5x5/7x7/9x9`, l.34-92) | Jamais référencées ; le vrai mécanisme passe par `CNMultiblock.REGISTRATE_MULTIBLOCK`. Ancienne implémentation abandonnée. | 🟡 | + +### 1.2 Méthodes inutilisées + +| Fichier:ligne | Détail | Priorité | +|---|---|---| +| `content/multiblock/controller/ReactorControllerBlockEntity.java:618-635` | `convertePattern(CompoundTag)` : variable `list` non utilisée, retourne toujours `null`, jamais appelée. | 🟡 | +| `content/multiblock/controller/ReactorControllerBlockEntity.java:637-654` | `FindController(char)` privée jamais appelée ; duplique le pattern statique de `CNMultiblock`. | 🟡 | +| `content/multiblock/core/ReactorCoreEntity.java:51-68` | Idem : `FindController(char)` jamais appelée. | 🟡 | +| `content/multiblock/input/item/ReactorInputEntity.java:73-90` | Idem : `FindController(char)` jamais appelée. | 🟡 | +| `content/multiblock/ReactorAssembler.java:132-136` | `getPlayersInRadius(...)` annotée `@Deprecated`, jamais appelée. | 🟢 | +| `content/multiblock/alarm/ReactorAlarmEntity.java:98-100` | `setController(...)` jamais appelée. | 🟢 | +| `foundation/utility/CreateNuclearLang.java:67-70` | `temporaryText(String)`, `@Deprecated`, aucun appelant. | 🟢 | +| `foundation/utility/TextUtils.java:45-75,116-119` | `renderMultilineDebugText`, `renderDebugText`, `translateWithFormatting`, `leftPad` : aucun appelant dans le code. | 🟢 | +| `net/nuclearteam/createnuclear/CNDamageTypes.java:10-16` | Méthode privée `key(String)` jamais appelée (`bootstrap()` vide). | 🟢 | + +### 1.3 Champs inutilisés + +| Fichier:ligne | Détail | Priorité | +|---|---|---| +| `content/multiblock/controller/ReactorControllerBlockEntity.java:60` | `public boolean test = true;` — champ de debug jamais lu ailleurs. | 🟡 | +| `content/multiblock/controller/ReactorControllerBlockEntity.java:70-71` | `public State powered = State.OFF;` assigné mais jamais lu ailleurs. | 🟢 | +| `content/multiblock/alarm/ReactorAlarmEntity.java:21` | Champ public `controller` jamais lu (hors `setController` lui-même mort). | 🟢 | +| `content/multiblock/IHeat.java:33-37` | Champ `intColor` et constructeur associé jamais utilisés (tous les enum values utilisent le constructeur `ChatFormatting`). | 🟢 | +| `net/nuclearteam/createnuclear/CNRecipeTypes.java:43,59,69,74` | Champ `isProcessingRecipe` assigné mais jamais lu. | 🟡 | +| `net/nuclearteam/createnuclear/CNAdvancement.java:46` | `public static final CreateNuclearAdvancement START = null,` jamais utilisée ailleurs. | 🟢 | +| `content/effects/VicinityEffect.java:22-27` | Paramètre constructeur `Consumer **Le piège récurrent, vérifié deux fois.** Un fichier absent n'est pas le seul symptôme d'une +> feature manquante. À deux reprises, la classe qui « manquait » n'était qu'un **point +> d'enregistrement** : le reste de la feature existait déjà côté NeoForge, complet et correct, +> mais **n'était référencé nulle part** — donc entièrement mort en jeu. +> **Avant de porter quoi que ce soit, chercher les classes NeoForge jamais référencées.** + +--- + +## 1. À ne pas porter — l'équivalent existe déjà + +**Ne pas recréer ces fichiers.** Le `diff` d'arborescence du §8 les listera toujours. + +### 1.1 Volontairement non portés — l'équivalent 1.21 est meilleur + +| Fichier Forge | Remplacé côté NeoForge par | +|---|---| +| `content/radiation/capability/IRadiationCapability` | **Data attachments NeoForge** — `RadiationCapability` expose `AttachmentType RADIATION`, lu via `entity.getData(RADIATION)` | +| `content/radiation/capability/RadiationProvider` | idem — la plomberie `ICapabilityProvider` de Forge n'a pas d'équivalent, ni de raison d'exister | +| `foundation/utility/SimplexNoise` | **`net.minecraft.world.level.levelgen.synth.SimplexNoise`** — `Maths` utilise déjà celui de vanilla | + +> `foundation/advancement/CriterionTriggerBase` est sorti de cette liste : le fichier existe +> désormais des deux côtés avec un contenu identique (commit `5d69829`, remplacement du +> `SimpleCriterionTrigger` vanilla par une base trigger custom, suivant l'évolution de Create). + +### 1.2 Présents sous un autre nom ou dans un autre package + +| Fichier Forge | Équivalent NeoForge | Pourquoi | +|---|---|---| +| `foundation/data/recipe/CNProcessingRecipeGen` | `foundation/data/recipe/CNRecipeProvider` | En 1.21 la classe n'hérite plus de `ProcessingRecipeGen` mais de `RecipeProvider`, et agrège les générateurs. Même rôle, nom aligné sur son parent | +| `foundation/events/overlay/IrradiatedOverlayRendererVision` | `foundation/events/overlay/RadiationOverlay` | Même rôle (overlay HUD de radiation), réécrit pour hériter d'une nouvelle base `EasingHudOverlay`. Porté le 14 août (commit `fa48da6`, « restore the radiation vision overlay ») | +| `content/multiblock/bluePrintItem/ReactorBluePrintItemPacket` | `ReactorBluePrintData` + `PatternData` | Le paquet réseau Forge (`SimplePacketBase`) est remplacé par deux records à `Codec`/`StreamCodec`, cohérent avec l'architecture data-component déjà validée en §7 pour `controller/` | + +> ✅ **`bluePrintItem/` déjà audité — dans [`PORTAGE_REACTEUR.md`](PORTAGE_REACTEUR.md), pas ici.** +> Contrairement à ce que disait la version précédente de ce document, ce sous-dossier n'a pas été +> laissé de côté : le « Lot 2bis » de `PORTAGE_REACTEUR.md` (9 août 2026) couvre la migration +> complète NBT → Data Components de `bluePrintItem/`, avec deux bugs réels trouvés et corrigés à +> cette occasion (thorium qui perdait ses barres à la réouverture du menu faute de tag +> `CNItemTags.FUEL`, et une config `CRods` dupliquée entre `CNCCommon`/`CNCServer` qui pouvait +> désynchroniser l'affichage du blueprint du calcul de chaleur réel). Vérifié le 16 août : les +> arborescences correspondent bien à la description de ce lot — Forge a 4 fichiers +> (`ReactorBluePrintItem`, `ReactorBluePrintItemPacket`, `ReactorBluePrintItemScreen`, +> `ReactorBluePrintMenu`), NeoForge en a 5 (mêmes moins le paquet réseau, plus +> `ReactorBluePrintData`/`PatternData`) — cohérent avec la suppression assumée du paquet réseau +> documentée dans ce lot. Rien à reporter ici. + +> ✅ **Résolu depuis le 7 août.** `SnowPowderRecipeGen` n'est plus une divergence de package : +> le commit `41f6176` (« move EnrichedRecipeGen/SnowPowderRecipeGen from foundation to the api +> package ») l'a ramené dans `api/data/recipe`, exactement au même chemin que Forge. +> +> ✅ **Sort de l'ancien vestige `api/data/recipe/EnrichedRecipeGen` — revérifié le 16 août, vivant +> et sain.** Existe des deux côtés au même chemin, avec le même rôle (classe de base des recettes +> d'enrichissement, lue par `CNRecipeTypes.ENRICHED`). Côté Forge, hérite de `ProcessingRecipeGen` +> (API 1.20.1) ; côté NeoForge, de `StandardProcessingRecipeGen` (API 1.21, +> conforme au reste du projet). `CNEnrichedRecipeGen` (`foundation/data/recipe/`) l'étend des deux +> côtés avec les deux mêmes recettes (`ENRICHING_CAMPFIRES`, `ENRICHED_YELLOWCAKE`), et est +> référencé et enregistré dans `CNRecipeProvider` côté NeoForge — pas de code mort. Rien à faire. + +--- + +## 2. Statut — plus aucun chantier de parité ouvert à ce niveau + +Les quatre chantiers listés ici le 7 août sont **désormais tous portés** : la compat Alex's +Caves et les mixins client (tous les deux dans le commit `41f6176` du 8 août — +`compat/Mods.java`, `compat/alexscave/AlexscaveCompat.java`, `CameraAccessor.java`, +`GameRendererMixin.java` existent des deux côtés, correctement enregistrés dans +`createnuclear.neoforge.mixins.json`), la vache irradiée (commit `5350638` du 15 août), et +l'abstraction `IrradiatedAnimal` (commit `7d16431` du 16 août, détail en §2.1). Cette section +n'a plus vocation à lister de travail restant ; elle garde son historique pour référence. + +--- + +### 2.1 `IrradiatedAnimal` — livrée le 16 août (commit `7d16431`) + +**✅ Fait.** `content/contraptions/irradiated/IrradiatedAnimal.java` existe désormais côté +NeoForge, porté depuis Forge quasi à l'identique — seuls changements imposés par l'API 1.21 : +`ForgeEventFactory.onLivingConvert` → `EventHooks.onLivingConvert`, et l'appel à `finalizeSpawn` +adapté à sa nouvelle signature à 4 arguments (`ServerLevelAccessor` au lieu de `ServerLevel`, +plus de paramètre `dataTag`). L'interface expose la même mécanique de conversion animal +irradié → vanilla que Forge (mêmes effets `DAMAGE_BOOST`/`CONFUSION`, même `EntityEvent +.ZOMBIE_CONVERTING`, même son `SOUND_ZOMBIE_CONVERTED`) — c'est le pendant de la guérison +zombie-villageois vanilla. + +`IrradiatedChicken` l'implémente, exactement comme côté Forge (`getNormalVariant()` → +`EntityType.CHICKEN`, `readFromVanilla`/`writeToVanilla` synchronisent `isChickenJockey`, un +`DATA_CONVERTING_ID` synchronisé porte l'état de conversion). Au passage, `IrradiatedChicken` a +aussi rattrapé le reste de son retard sur Forge : ponte d'œufs (`eggTime`), support chicken-jockey +complet (XP bonus, règle de despawn, sauvegarde), qui manquaient côté NeoForge. `CreateNuclear +.init(...)` enregistre `EntityType.CHICKEN → CNEntityType.IRRADIATED_CHICKEN` dans +`VANILLA_TO_IRRADIATED`, comme Forge. + +**Piège 1.21 rencontré en portant `getExperienceReward()` :** cette méthode est désormais `final` +sur `LivingEntity` (`getExperienceReward(ServerLevel, Entity)`) — impossible à surcharger. Le hook +overridable équivalent est `protected int getBaseExperienceReward()`. Idem pour `positionRider` : +le décalage manuel par `getMyRidingOffset()` que faisait Forge n'a plus d'équivalent, la classe +vanilla `Chicken` de cette version ne fait plus que repositionner `yBodyRot` — copié tel quel côté +NeoForge plutôt que de réinventer un offset. + +**Portée assumée, alignée sur Forge et non étendue :** seul `IrradiatedChicken` implémente +`IrradiatedAnimal`, exactement comme côté Forge — `Chat`/`Loup`/`Vache` n'implémentent pas +l'interface là-bas non plus. Un refactor qui irait plus loin (faire hériter chat/loup/vache d'une +base commune) serait une **amélioration NeoForge au-delà de la parité Forge**, pas un chantier de +portage : à ne considérer que si le besoin apparaît, pas pour « finir » ce document. + +**Effet de bord découvert pendant ce chantier — bug de régression, pas un écart Forge/NeoForge :** +en réécrivant `IrradiatedCat` pour suivre de plus près le `Cat` vanilla (suppression des 3 classes +de goal dédiées `IrradiatedCatAvoidEntityGoal`/`RelaxOnOwnerGoal`/`TemptGoal`, remplacées par des +classes imbriquées calquées sur vanilla), `defineSynchedData()` avait régressé vers l'ancienne +signature sans paramètre (`protected void defineSynchedData()` au lieu de +`defineSynchedData(SynchedEntityData.Builder builder)`), plus valide en 1.21 — l'override +n'en était plus un, `IS_LYING`/`RELAX_STATE_ONE` et tout ce qu'apporte `super` n'étaient jamais +enregistrés dans le builder, d'où un crash immédiat au spawn (`IllegalStateException: ... has not +defined synched data value 19`). Corrigé dans le même commit en repassant par +`builder.define(...)` + `super.defineSynchedData(builder)`, sur le modèle de `IrradiatedWolf`. +**À garder en tête pour toute future entité :** un override qui compile sans erreur (signature +différente = simple surcharge, pas d'erreur du compilateur) peut quand même être un override +*raté* silencieusement — vérifier que la signature correspond bien à celle de la classe parente +en 1.21, pas à une version antérieure copiée-collée. + +--- + +### 2.2 Nouveautés NeoForge non documentées, à surveiller + +Des fichiers sans équivalent Forge sont apparus depuis le 7 août sans être suivis ici. La +plupart sont vivants et légitimes (infrastructure data attachments/components, goals IA du chat +irradié) ; ceux ci-dessous méritent une action : + +> ✅ **`IrradiatedWoldCollarLayer.java` retirée** (commit `4918bf7`, « remove the orphaned +> IrradiatedWoldCollarLayer render layer »). Jamais ajoutée via `addLayer(...)` à +> `IrradiatedWolfRenderer` (`render()` était un no-op vide) — tentative de feature (collier coloré +> du loup irradié apprivoisé) commencée et jamais branchée, n'existait pas côté Forge. Supprimée +> plutôt que terminée. + +`CNAttachmentTypes`, `CNDataComponents`, les goals IA du chat (`IrradiatedCatAvoidEntityGoal`, +`IrradiatedCatRelaxOnOwnerGoal`, `IrradiatedCatTemptGoal`), `FluidLockManager`, +`EasingHudOverlay`, `CNDamageTypeTagsProvider` : tous référencés et vivants, rien à signaler. + +> ✅ **`CommentEventClients.java` fusionnée dans `CNClientEvent` puis supprimée.** N'était pas du +> code mort — `@EventBusSubscriber` auto-découverte par NeoForge, elle portait l'enregistrement +> des layers de modèle d'entités (`CNEntityType.registerModelLayer`, essentiel pour l'affichage +> de chat/poulet/loup/vache irradiés). Le problème était le découpage et le nom (coquille +> probable de « CommonEventClients », sans équivalent Forge ni convention du projet) : côté Forge, +> cet appel vit directement dans `CNClientEvent.registerLayers`, aux côtés du reste de +> l'enregistrement client. La méthode `registerLayers` a été rapatriée dans `CNClientEvent` +> (alignement avec Forge), et le fichier à part supprimé. + +> ✅ **`ReactorGaugeOverrides.java` a disparu du code depuis la dernière mise à jour** — le +> fichier orphelin signalé précédemment a été retiré (reste seulement mentionné dans ce doc et +> dans `PORTAGE_REACTEUR.md`/`AUDIT_NEOFORGE.md`). Pas encore vérifié si la feature du gauge de +> cadre a été branchée ailleurs ou simplement abandonnée — à confirmer si le besoin ressurgit. +> +> ✅ **`logoFile` corrigé.** `neoforge.mods.toml` (`logoFile = "icon.png"`) pointait vers un +> fichier qui vivait dans `src/main/resources/META-INF/icon.png` — NeoForge résout `logoFile` +> relativement à la racine du jar (comme `assets/`, `data/`), pas au dossier `META-INF/` qui +> contient le toml lui-même. Déplacé vers `src/main/resources/icon.png` (racine des resources, +> sibling de `META-INF/`), la convention des templates NeoForge/Forge MDK. +> **Piège séparé rencontré en vérifiant le fix :** `bin/main` (sortie de compilation IntelliJ, +> distincte de `build/` géré par Gradle) peut rester figée sur une ancienne copie de +> `neoforge.mods.toml`/des resources si la run configuration charge cette sortie au lieu de +> `build/resources/main`. Un `Rebuild Project` (ou passer « Build and run using » sur Gradle dans +> les réglages Gradle d'IntelliJ) est nécessaire pour voir tout changement de resources se +> refléter en jeu — sans lien avec le portage Forge/NeoForge, à garder en tête pour tout futur +> « ça ne marche pas alors que le fichier est bon ». +> +> ✅ **`CNShapelessRecipeGen.java` supprimé** (commit `93975b3`), plutôt que rebranché. Sa +> registration dans `CreateNuclearDatagen` était déjà commentée et le générateur était mort code +> depuis le début — pas de recettes shapeless (cloth, etc.) perdues puisqu'elles n'étaient jamais +> produites. Sorti de cette liste et de l'ordre de travail (§5). + +--- + +## 3. Écarts internes aux fichiers partagés — non audités + +Ces fichiers existent des deux côtés mais divergent fortement. **Un gros diff n'est pas une +preuve de feature manquante** : l'API 1.21 en explique une grande part. Aucun n'a été audité +ligne à ligne, contrairement au domaine réacteur. + +| Fichier | Lignes divergentes (7 août) | Lignes divergentes (14 août) | Statut au 16 août | +|---|---|---|---| +| `CNBlocks` | 701 | 707 | **audité ligne à ligne, §3.3** — 1 bug réel corrigé | +| `CNItems` | 457 | 472 | **audité ligne à ligne, §3.3** — parité confirmée | +| `foundation/advancement/CNAdvancement` | 394 | 416 | **audité ligne à ligne, §3.4** — ✅ 6 advancements réactivées et corrigées | +| `content/contraptions/irradiated/cat/IrradiatedCat` | 384 | 380 | 40 | +| `foundation/data/recipe/CNStandardRecipeGen` | 395 | 394 | **audité ligne à ligne, §3.4** — 6 recettes de décompactage en trop, ✅ acceptées tel quel | +| `compat/jei/CreateNuclearJEI` | 344 | 333 | **audité ligne à ligne, §3.4** — sain, superset de Forge | +| `content/contraptions/irradiated/wolf/IrradiatedWolf` | 333 | 333 | **audité ligne à ligne, §3.4** — ✅ aligné sur Forge (apprivoisement bloqué, but de fuite restauré) | +| `content/contraptions/irradiated/chicken/IrradiatedChicken` | — | — | 111 *(nouveau — n'était pas suivi ici avant le portage du 16 août)* | +| `CNCreativeModeTabs` | 249 | 249 | non revérifié | +| `content/radiation/capability/RadiationCapability` | 186 | 199 | **audité ligne à ligne, §3.4** — divergence de persistance, ✅ assumée volontairement | + +`IrradiatedCat` chute de 380 à 40 lignes divergentes : la réécriture du 16 août aligne l'IA du +chat sur `Cat` vanilla plutôt que de la dupliquer dans des classes de goal maison (§2.1), donc le +fichier **se rapproche** de Forge au lieu de s'en éloigner — l'inverse de la tendance habituelle +de ce tableau. `IrradiatedWolf` reste stable à 333, comme prévu (ni touché ni concerné par ce +chantier). Seules les trois lignes concernées par le travail du 16 août ont été revérifiées ; +les autres restent au dernier relevé du 14 août — dérives modestes (+6 à +22 lignes), cohérentes +avec les commits récents (`RadiationCapability` refactorée en attachment sérialisable/ +synchronisable le 9 août, routage des dégâts le 8 août). Rien d'alarmant, mais aucun de ces +fichiers n'est audité ligne à ligne — la mise en garde ci-dessous reste entière. + +> **Ce n'est pas théorique.** Sur les six bugs trouvés en testant le réacteur en jeu, **deux +> étaient cachés dans `CNBlocks`** : la capacité de stress de la sortie à `10240` au lieu de +> `64000` (SU divisé par 6,25) et quatre `addLayer` manquants — dont `reinforced_glass` qui +> rendait donc opaque. Aucun des deux n'était visible dans un diff d'arborescence. +> +> **Méthode qui a marché :** ne pas lire le diff en entier, mais partir d'un symptôme observé en +> jeu et remonter. C'est plus rapide et ça ne trouve que des bugs réels. +> +> ✅ **Capacité de stress de `REACTOR_OUTPUT` — revérifiée le 16 août, déjà corrigée.** +> `BlockStressValues.CAPACITIES.register(block, () -> 64000.0)` est identique des deux côtés +> (`CNBlocks.java` ligne 183 Forge / 191 NeoForge), et un `grep -rn "10240"` sur les deux dépôts ne +> renvoie plus rien. Réglé avant cette session, sans commit dédié retrouvé — probablement corrigé +> dans le même lot que le reste du portage réacteur. + +### 3.3 Audit ligne à ligne — `CNBlocks` / `CNItems` (16 août 2026) + +Audit complet demandé pour clore la ligne « continu » du §5. Les deux fichiers ont été lus +intégralement des deux côtés (623↔690 lignes pour `CNBlocks`, 436↔452 pour `CNItems`) et comparés +bloc par bloc / item par item, plutôt que jugés sur la taille du diff brut. + +**Parité de la liste (aucune entrée manquante ou en trop) :** +- `CNBlocks` : 27 `.block("...")` de chaque côté, mêmes 27 noms. +- `CNItems` : 29 `.item(...)` de chaque côté (28 nommés + 1 anonyme), mêmes noms. + +**Faux positif éliminé — les `addLayer` ne manquent pas, ils ont changé de mécanisme.** Six blocs +(`REACTOR_FRAME`, `REACTOR_ROD_INPUT`, `REACTOR_FLUID_INPUT`, `REINFORCED_GLASS`, +`ENRICHING_FIRE`, `ENRICHING_CAMPFIRE`) ont un `.addLayer(() -> RenderType::X)` côté Forge, absent +côté NeoForge. Vérifié sur les modèles JSON générés (`rod_input.json`, les 4 `frame_*.json`, +`fluid_input*.json`, `block.json`/`block_off.json` du campfire, `enriching/fire/*.json`) : chacun +déclare désormais `"render_type": "cutout_mipped"` (ou `"cutout"`/défini via `.renderType(...)` +dans le blockstate builder pour `REINFORCED_GLASS`) **directement dans le modèle**, le mécanisme +1.21 qui remplace l'ancien layer Java. **Ceci referme définitivement le doute laissé en §3 sur +les « 4 `addLayer` manquants »** — aucun des deux mécanismes de rendu n'est cassé, c'est un +remplacement correctement fait, pas un oubli. + +**Bug réel trouvé et corrigé — rendement de minerai divergent sur uranium/plomb.** Comparé aux +JSON de loot table générés (`data/createnuclear/loot_table/blocks/*.json`), 4 minerais avaient +perdu leur fonction `set_count` de base : + +| Bloc | Forge (`set_count` avant bonus fortune) | NeoForge avant correctif | +|---|---|---| +| `uranium_ore` / `deepslate_uranium_ore` | `uniform(3.0–4.0)` | **absent** — juste `ore_drops` (comme le fer vanilla, ~1 item) | +| `lead_ore` / `deepslate_lead_ore` | `uniform(2.0–4.0)` | **absent** | +| `thorium_ore` / `deepslate_thorium_ore` | `uniform(2.0–5.0)` | présent, conforme (contrôle) | +| `nitrate_ore` / `deepslate_nitrate_ore` | pas de `set_count` côté Forge non plus | conforme (contrôle) | + +Cause probable : lors du portage de `Enchantments.BLOCK_FORTUNE` (champ statique Forge/1.20) vers +le `HolderLookup`-based `Enchantments.FORTUNE` de 1.21, `URANIUM_ORE`/`LEAD_ORE` (et leurs variantes +deepslate) sont passés à l'aide `ApplyBonusCount.addOreBonusCount(...)` (le helper vanilla standard, +sans `set_count`) au lieu de garder l'appel à `SetItemCountFunction.setCount(UniformGenerator +.between(...))` que `THORIUM_ORE` a conservé correctement. Conséquence en jeu : ces 4 minerais +donnaient nettement moins de matière première brute que Forge (pas de plancher garanti 2–4/3–4, +juste le comportement fer/or vanilla). + +**Corrigé** dans `CNBlocks.java` : réintroduction du `.apply(SetItemCountFunction.setCount( +UniformGenerator.between(...)))` sur les 4 loot tables concernées, avant le `ApplyBonusCount` +existant. Recompilé (`./gradlew compileJava`) et revérifié via `./gradlew runData` : les 4 JSON +générés portent maintenant `"function": "minecraft:set_count"` avec les bornes de Forge. +**Non testé en jeu** (récolte réelle avec/sans fortune) — à ajouter au §4. + +**Point mineur non corrigé, à surveiller :** le nom de `formula` sous `apply_bonus` diverge de +Forge sur tous les minerais concernés (`ore_drops` côté NeoForge contre `uniform_bonus_count` +côté Forge, y compris pour `thorium_ore` où le `set_count` de base, lui, est identique) — cet +écart vient du choix d'helper Java (`addOreBonusCount` vs `addUniformBonusCount`) et pourrait +légèrement changer la courbe du bonus fortune sans toucher au plancher garanti. Pas retouché ici +faute de certitude sur l'intention exacte ; à revoir si un joueur signale un rendement fortune +anormal sur ces minerais. + +**Autres écarts relevés, aucun n'est un bug :** +- `CNBlocks`/`CNItems` NeoForge appellent chacun `CreateNuclear.REGISTRATE.setCreativeTab( + CNCreativeModeTabs.MAIN)` dans un bloc `static {}` en tête de fichier, en plus de l'appel déjà + présent dans `CNPaletteBlocks` (le seul endroit qui l'appelle côté Forge). Redondant mais + inoffensif — fixe le même onglet, garantit juste l'ordre d'init sans dépendre du chargement de + `CNPaletteBlocks` en premier. +- `ANTI_RADIATION_HELMETS` porte un tag `CNItemTags.ANTI_RADIATION_HELMET` absent côté Forge et + absent des 3 autres pièces d'armure ; vérifié utilisé dans `foundation/events/overlay/ + HelmetOverlay.java` (détection du casque porté pour l'overlay de vision) — vivant, pas mort code. +- Divergences de typage Java (`ItemEntry` généré en un seul bloc côté Forge, + scindé en deux blocs `ItemEntry`/`ItemEntry` côté NeoForge), + `.transform(setColorComponent(Cloths.DEFAULT))` et le `if (cloth == Cloths.DEFAULT) continue` + dans les recettes smithing des armures — cohérent avec le passage NBT mutable → DataComponents + déjà documenté en §6, pas une divergence de comportement en jeu. + +**Conclusion : l'audit ligne à ligne de `CNBlocks`/`CNItems` est fait pour cette passe, un bug réel +trouvé et corrigé.** La ligne « continu » du §5 reste néanmoins en place par nature (voir sa +justification) — un futur symptôme en jeu peut toujours révéler autre chose, mais aucun résidu +connu ne traîne sur ces deux fichiers à ce jour. + +### 3.4 Audit ligne à ligne — `CNAdvancement`, `CNStandardRecipeGen`, `CreateNuclearJEI`, +`RadiationCapability`, `IrradiatedWolf` (16 août 2026) + +Les cinq fichiers que le tableau du §3 marquait « non revérifié » depuis le 14 août ont été lus +intégralement des deux côtés et comparés ligne à ligne, comme pour `CNBlocks`/`CNItems` (§3.3). +**Contrairement à cette dernière passe, celle-ci trouve plusieurs divergences comportementales +réelles, non corrigées ici** — ce ne sont pas des « faux positifs de diff », le §0 avait raison +de garder la mise en garde ouverte. + +#### 3.4.1 `CNAdvancement` — ✅ corrigé, 6 advancements réactivées + +La majorité du diff (~400 lignes) est de l'adaptation d'API 1.21 normale (`Advancement`/ +`AdvancementHolder` + codecs, `RecipeCraftedTrigger` prenant désormais une `List` au lieu d'un `ItemPredicate` construit, dossier `data//advancement/` au singulier). +Mais **6 advancements existaient et étaient actives côté Forge, et étaient commentées en bloc +(`/* ... */`) côté NeoForge** — donc absentes du datapack généré, sans erreur de compilation +puisque la syntaxe de champs chaînés restait valide autour du bloc commenté : + +| Advancement | Forge | NeoForge (avant correctif) | +|---|---|---| +| `anti_radiation_armor` | active | commentée | +| `avoiding_cancer` | active | commentée | +| `dye_anti_radiation_armor` | active | commentée | +| `feeding_the_reactor` (`REACTOR_ROD_INPUT`) | active | commentée | +| `fueling_the_reactor` (`REACTOR_FLUID_INPUT`) | active | commentée | +| `unlimited_power` (`REACTOR_OUTPUT`) | active | commentée | + +Toutes les autres advancements (racine, chaînes uranium/thorium/azote/charbon/plomb, réacteur +casing/controller/core/cooler/frame, T1-T3, blueprint, `silence_the_core`, `no_time_to_die`, +`crunchy_uranium`, `cryogenic_baptism`, `reinforced_glass`, `craft_enriching_campfire`) +correspondent 1:1 (même id, titre, description, icône, parent `after()`, même type de trigger +une fois l'adaptation d'API prise en compte). + +> ✅ **Corrigé le 16 août.** Les 6 blocs ont été décommentés. `ANTI_RADIATION_ARMOR`, +> `DYE_ANTI_RADIATION_ARMOR`, `REACTOR_ROD_INPUT`/`feeding_the_reactor`, +> `REACTOR_FLUID_INPUT`/`fueling_the_reactor` et `REACTOR_OUTPUT`/`unlimited_power` n'avaient +> besoin d'aucune adaptation — ils compilaient tels quels une fois décommentés. +> +> **`AVOIDING_CANCER` avait un vrai piège 1.21 caché dans son trigger, révélé seulement une fois +> décommenté :** `CriterionTrigger.getId()` n'existe plus en 1.21 — les triggers ne portent plus +> leur propre id, ils sont identifiés via leur registre (`BuiltInRegistries`/`CriteriaTriggers`). +> Le code Forge original faisait `new PlayerTrigger.TriggerInstance(CriteriaTriggers +> .INVENTORY_CHANGED.getId(), EntityPredicate.wrap(...))` — un vieux contournement 1.16-1.20 pour +> réutiliser l'écoute de l'événement « inventaire modifié » avec un prédicat de joueur personnalisé +> (ici, `FULL_ARMOR` : les 4 pièces d'armure anti-radiation équipées). Remplacé par le mécanisme +> 1.21 : construire directement un `InventoryChangeTrigger.TriggerInstance(Optional, Slots +> .ANY, List.of())` et l'envelopper via `CriteriaTriggers.INVENTORY_CHANGED.createCriterion(...)` +> — la même méthode déjà utilisée ailleurs dans ce fichier (`InventoryChangeTrigger.TriggerInstance +> .hasItems(...)`, `builtinTrigger.createCriterion(...)`). Comportement inchangé : toujours +> déclenché sur `minecraft:inventory_changed` (l'équipement d'armure fait partie de l'inventaire +> joueur), toujours conditionné à `FULL_ARMOR`. +> +> Vérifié : `./gradlew compileJava` passe, `./gradlew runData` régénère les 6 JSON manquants dans +> `src/generated/resources/data/createnuclear/advancement/`. **Non testé en jeu** (le +> déclenchement effectif au moment d'équiper l'armure complète) — à ajouter au §4. + +#### 3.4.2 `CNStandardRecipeGen` — recettes de décompactage en trop côté NeoForge + +Le diff de ~150 lignes en plus côté NeoForge (548 vs 398) s'explique à ~90% par de la migration +d'API légitime : le remplacement de `ModdedCookingRecipeResult` (record simple, Forge) par +`ModdedCookingRecipeOutputShim` (record + `Serializer` + `FakeItemStack`, ~115 lignes, la +plomberie codec/`RecipeSerializer` qu'exige 1.21 pour ce même mécanisme de compat cuisson +« moddée »), plus le passage à `RecipeOutput`/conditions (`ICondition`, `withConditions`). + +**Divergence réelle trouvée :** `metalCompacting()` (Forge lignes 99-116, NeoForge lignes 177-199) +ajoute côté NeoForge une recette supplémentaire par itération, absente de Forge : + +```java +result = create(currentEntry).returns(9) + .withSuffix("_from_decompacting") + .unlockedBy(nextEntry::get) + .viaShapeless(b -> b.requires(nextIngredient.get())); +``` + +Ça génère 6 recettes de « décompactage » (lingot/bloc → 9 du palier inférieur) pour le plomb, +l'acier et le thorium, qui n'existent pas côté Forge. + +> ✅ **Accepté tel quel pour l'instant, close.** Décision du 16 août : feature de confort ajoutée +> volontairement pendant le portage NeoForge, pas un bug de portage. Gardée en l'état — elle +> pourra être retirée plus tard si besoin, mais ce n'est pas un chantier ouvert aujourd'hui. +> Si elle disparaît un jour, ce sera un choix de design assumé, pas une correction de parité. + +Point mineur sans impact : les deux fichiers portent des méthodes utilitaires jamais appelées +nulle part (`createSpecial`/`blastCrushedMetal`/`recycleGlass`/... côté NeoForge, +`smokerRecipe`/`furnaceRecipe`/... côté Forge) — du code mort hérité du template `RecipeGen` de +Create des deux côtés, sans impact en jeu. + +#### 3.4.3 `CreateNuclearJEI` — sain, le diff est un superset NeoForge + +Les deux catégories JEI (`fan_enriched`, `fan_snow_powder`) sont enregistrées à l'identique des +deux côtés, mêmes catalyseurs, mêmes icônes, mêmes classes de rendu (`FanEnrichedCategory`, +`FanSnowPowderCategory`, présentes dans les deux arbres). **La catégorie « Cryogenic fan » (snow +powder) mentionnée en attente au §4 est confirmée présente et correctement câblée** — pas de +travail restant sur ce point précis pour JEI. + +Le diff de taille (312 Forge vs 249 NeoForge, donc NeoForge plus **court**) vient de la relocation +du `CategoryBuilder` (Forge en réimplémente ~20 méthodes utilitaires jamais appelées par +`loadCategories()` ; NeoForge en hérite directement de `CreateRecipeCategory.Builder` côté +Create 1.21, 12 lignes) et de renommages d'API de recettes (`Recipe` → `RecipeHolder`). +NeoForge ajoute même 5 enregistrements absents de Forge (subtypes de fluide potion, ingrédients +extra, gestionnaires d'ingrédients fantômes pour plusieurs écrans, transfer handler universel, +recettes de coloration toolbox) — vraisemblablement un resynchronisation sur un template Create +JEI plus récent au moment du portage. **Rien à corriger.** + +#### 3.4.4 `RadiationCapability` — divergence de persistance de la contagion + +Les seuils, la formule de résistance (`Mth.clamp(attribute.getValue(), 0.0, 1.0)`), le +recalcul de `radiation` à chaque changement de hash d'inventaire (ni l'un ni l'autre ne fait +« décroître » la radiation dans le temps — elle est entièrement recalculée depuis les items +détenus) et la logique de rafraîchissement d'effet (durée 100 ticks, relance sous 40) sont +identiques des deux côtés, au tick et au chiffre près — y compris un bug latent préexistant +partagé par les deux versions (la branche `amplifierLevel3` réutilise `amplifierLevel2` au lieu +d'un palier distinct, Forge L230-233 / NeoForge L209-212 — pas une divergence Forge/NeoForge, +donc hors périmètre de ce document). + +**Divergence trouvée — le jeu de champs persistés diffère :** + +| | Forge (`RadiationProvider.serializeNBT`) | NeoForge (`RadiationCapability.CODEC`) | +|---|---|---| +| `radiation`, `hash`, `lastBiome` | persistés | persistés | +| `contagionDose`, `contagionTicks` | **jamais persistés** (purement en mémoire) | **persistés** | + +Conséquence en jeu : côté Forge, une contagion active est silencieusement effacée à chaque +déchargement/rechargement de chunk (reco du joueur, mob qui se recharge) — la contagion ne +survit jamais à une sauvegarde. Côté NeoForge, elle survit désormais et continue de décroître +après rechargement. + +> ✅ **Divergence assumée volontairement, close.** Décision du 16 août : la persistance +> `contagionDose`/`contagionTicks` reste telle quelle côté NeoForge. Ce n'est pas un alignement +> strict sur Forge, mais un comportement jugé correct (voire préférable) — la contagion ne doit +> pas s'effacer gratuitement par un simple rechargement de chunk. **Ne pas « corriger » ce point +> lors d'une synchro Forge → NeoForge.** + +Persistance à la mort : vérifiée absente des deux côtés (ni `PlayerEvent.Clone` côté Forge, ni +`.copyOnDeath()` sur `CNAttachmentTypes.RADIATION` côté NeoForge) — la radiation/contagion se +réinitialise au respawn sur les deux plateformes, comportement cohérent bien que probablement +non intentionnel à l'origine. Rien à faire sur ce point précis : au moins les deux versions +s'accordent. + +#### 3.4.5 `IrradiatedWolf` — ✅ corrigé, aligné sur Forge (apprivoisement bloqué, but de fuite restauré) + +**Point de vérification prioritaire, confirmé sain dès l'audit :** contrairement à `IrradiatedCat` +(§2.1), `defineSynchedData` avait la bonne signature 1.21 côté NeoForge (`protected void +defineSynchedData(SynchedEntityData.Builder builder)`, appelle `super.defineSynchedData(builder)`, +enregistre `DATA_INTERESTED_ID`/`DATA_REMAINING_ANGER_TIME` via `builder.define(...)`) — aucun +risque de crash au spawn ici, rien à corriger sur ce point. + +**Divergences trouvées, toutes corrigées le 16 août :** + +- **But de panique manquant → réintroduit.** Forge enregistre `new WolfPanicGoal(1.5)` à la + priorité 1. Absent côté NeoForge (ni le goal, ni la classe). La classe interne `WolfPanicGoal` + (paniquer si `isFreezing()` ou `isOnFire()`) et son enregistrement ont été copiés à l'identique + depuis Forge. +- **Apprivoisement/armure complet → retiré, aligné sur le blocage WIP de Forge.** Forge bloque + volontairement l'apprivoisement : l'interaction nourriture appelle + `AnimalUtil.blockTamingWip(player, level())`. NeoForge implémentait un apprivoisement complet + (`tryToTame`, `EventHooks.onAnimalTame`) plus tout un sous-système d'armure de loup absent de + Forge (`canUseSlot`, `actuallyHurt`, `canArmorAbsorb`, `hurtArmor`, `hasArmor`) — vraisemblablement + un pull complet de la parité avec le `Wolf` vanilla 1.21 fait pendant le portage, sans revue + explicite de la portée. **Décision : aligner sur Forge.** `mobInteract` réécrit sur le modèle + Forge (nourrir un loup apprivoisé soigne toujours ; nourrir un loup non apprivoisé appelle + `AnimalUtil.blockTamingWip` au lieu de tenter l'apprivoisement à l'os) ; les 6 méthodes d'armure + supprimées avec leurs imports devenus morts (`ItemParticleOption`, `DamageTypeTags`, + `ItemAbilities`, `EnchantmentHelper`/`EnchantmentEffectComponents`, `Ingredient`, `EventHooks`). + `applyTamingSideEffects()` — le hook 1.21 qui remplace le `setTame(boolean)` overridé de Forge — + est conservé (c'est la bonne mécanique 1.21, pas l'armure) mais son `TAME_HEALTH` est ramené de + `40.0F` à `20.0F` pour matcher exactement la valeur Forge. +- **Source de nourriture — divergence non touchée, assumée.** Forge lie l'éligibilité nourriture/ + apprivoisement à `CNItems.YELLOWCAKE` uniquement (`AnimalUtil.isFood`) ; NeoForge vérifie + `CNTags.CNItemTags.FUEL.tag`, un ensemble plus large. Comme le loup ne s'apprivoise plus (WIP + bloqué des deux côtés), cette différence n'affecte que le prompt « je vais essayer de + t'apprivoiser » et le soin d'un loup déjà apprivoisé par commande — jugée mineure, non alignée + ici. À revoir si besoin. +- **`getStandingEyeHeight` — ⚠️ le vrai piège de cette passe, plus profond que prévu.** L'audit + initial pensait qu'il suffisait de reporter l'override Forge (`dimensions.height * 0.8F`) tel + quel. **Faux : ce hook n'existe plus du tout en 1.21.** `Entity.getEyeHeight(Pose)` est devenu + `final` (`return this.getDimensions(pose).eyeHeight();`), donc tout override de + `getStandingEyeHeight(Pose, EntityDimensions)` **compile sans erreur mais ne s'exécute jamais** — + exactement la même classe de piège que la régression `defineSynchedData` du chat (§2.1), + découverte ici en ajoutant `@Override` explicitement et en laissant le compilateur le confirmer + (`error: method does not override or implement a method from a supertype`). Le mécanisme 1.21 + correct est `EntityType.Builder.eyeHeight(float)` au moment de l'enregistrement du type + d'entité. Corrigé pour le loup dans `CNEntityType.java` : + `.properties(p -> p.sized(0.6f, 0.85f).eyeHeight(0.68f))` (0.85 × 0.8, le ratio Forge), et + l'override mort supprimé de `IrradiatedWolf.java`. + > ✅ **`IrradiatedCat`/`IrradiatedCow` — confirmés porteurs du même override mort (ligne 339 du + > chat, ligne ~97 de la vache, vérifié par lecture directe), mais volontairement non corrigés + > ici et sortis de ce document.** Décision du 16 août : une vraie passe d'intégration est prévue + > sur ces deux entités, qui ira au-delà d'un simple correctif ponctuel — but explicite de + > supprimer autant que possible les « copies » de mobs vanilla (le même travail qui a déjà réduit + > `IrradiatedCat` de 380 à 40 lignes divergentes en §2.1, à poursuivre/étendre). Corriger + > `getStandingEyeHeight` isolément ici serait du travail jeté à la prochaine passe. **Ne pas + > traiter comme un chantier de parité Forge/NeoForge** — c'est un refactor NeoForge au-delà de la + > parité, à faire dans ce cadre-là, pas ici. +- **`canBeLeashed` — corrigé, et confirme que la signature 1.21 est bien no-arg.** Forge : + `!isAngry() && super.canBeLeashed(player)` (avec paramètre `Player`, API 1.20.1). Testé avec + `@Override` : `public boolean canBeLeashed()` **sans paramètre** compile et override bien en + 1.21 (contrairement à `getStandingEyeHeight` ci-dessus — la suppression du paramètre `Player` + est un vrai changement d'API 1.21, pas un override mort). L'appel à `super.canBeLeashed()` + manquant a été rajouté : `return !this.isAngry() && super.canBeLeashed();`. + +Aucun mécanisme de conversion irradié → loup vanilla n'existe dans ce fichier, ni d'un côté ni de +l'autre — cohérent avec §2.1 : seul `IrradiatedChicken` implémente `IrradiatedAnimal` des deux +côtés, le loup ne fait pas partie de ce contrat chez Forge non plus. + +Vérifié : `./gradlew compileJava` et `./gradlew runData` passent. **Non testé en jeu** (le +blocage effectif de l'apprivoisement, le but de fuite en situation de feu/gel, la hauteur des +yeux) — à ajouter au §4. + +--- + +### 3.1 Recettes — diff des JSON générés + +Le diff des `.java` cache mal les recettes manquantes ; celui des JSON générés les montre +directement. Commande dans le §8. + +**Corrigé** (symptôme signalé : le concentré d'azote refroidi ne servait à rien) — toute la +chaîne de l'azote était morte, **cassée aux deux bouts** : + +| Étape | Recette | État avant | +|---|---|---| +| nitrate → concentré d'azote | `smelting` + `blasting` | absente de `CNStandardRecipeGen` | +| concentré → concentré refroidi | `snow_powder` | absente — c'est le §2.1, porté depuis | +| concentré refroidi + glace → azote liquide | `mixing` | absente de `CNMixingRecipeGen` | + +Seul le fluide `LIQUID_NITROGEN` était enregistré — donc obtenable uniquement en créatif. + +**Reste à traiter — revérifié le 14 août, aucune de ces trois lignes n'a bougé depuis le 7 août :** + +| Recette Forge | Absente côté NeoForge | +|---|---| +| `mixing/thorium_fluid` | oui — toujours absente. Un `compacting/thorium_fluid_to_thorium_ingot.json` existe désormais (sens fluide → lingot), mais rien ne produit le fluide lui-même : `CNFluids.THORIUM` reste inobtenable hors créatif | +| `crafting/thorium_block_from_compacting` · `crafting/thorium_ingot_from_compacting` | oui — `THORIUM_COMPACTING` manque toujours dans `CNStandardRecipeGen` | +| `mechanical_crafting/reactor_alarm` | oui | + +> ✅ **Corrigé.** Commit `93975b3` (« fix(recipe-gen): stop crushing/washing recipe generators +> from leaking into the create namespace »). Cause : `ProcessingRecipeGen.create(() -> ingrédient, +> …)`, l'overload à 2 arguments de Create, hardcode `Create.ID` comme namespace par défaut au lieu +> du namespace du générateur — un choix différent de Forge, où l'ancienne surcharge prenait le +> namespace du générateur. `CNCrushingRecipeGen` (6 recettes) et `CNWashingRecipeGen` (1 recette, +> via `moddedCrushedOreCustom`) appelaient cet overload sans namespace explicite, ce qui générait +> les JSON sous `data/create/recipe/` et **écrasait des recettes du jar de Create** +> (`crushing/raw_copper`, `crushing/raw_zinc`, `crushing/raw_uranium_block`, +> `splashing/crushed_raw_lead`). +> +> **Correctif retenu :** plutôt que de passer `CreateNuclear.MOD_ID` à chaque appel, override de +> la seule surcharge fautive dans chacun des deux générateurs : +> ```java +> @Override +> protected GeneratedRecipe create(Supplier singleIngredient, UnaryOperator transform) { +> return create(CreateNuclear.MOD_ID, singleIngredient, transform); +> } +> ``` +> Aucun appel existant à changer, et ça sécurise aussi les futures recettes ajoutées via ce +> pattern ainsi que les helpers hérités de Create (`WashingRecipeGen.convert`/`crushedOre`) qui +> passent par le même overload en interne. +> +> Vérifié : `find .../data/create -name '*.json'` ressort vide (hors tags) après régénération du +> datagen ; les 7 JSON concernés sont réapparus sous `data/createnuclear/recipe/`. +> +> **Audité au passage, les 10 autres générateurs de recettes du projet sont sains** — chacun +> passe par le namespace du mod pour une raison différente (surcharge par nom, `ResourceLocation` +> explicite via `CreateNuclear.asResource(...)`, ou classe de base custom qui ne reproduit pas le +> hardcode de Create). Seule note en passant, sans lien avec ce bug : `CNStandardRecipeGen. +> createSpecial()` (~ligne 127) hardcode `Create.asResource(...)`, mais la méthode n'est jamais +> appelée nulle part dans le repo — code mort, aucun impact en jeu. + +### 3.2 Icônes d'inventaire des armures anti-radiation colorées — divergence assumée avec Forge + +✅ **Corrigé le 15 août.** Symptôme : au lancement, `ModelManager` loggait `Missing textures in +model createnuclear:default_anti_radiation_{helmet,chestplate,leggings,boots}#inventory` pour +les 16 couleurs, alors que les fichiers PNG existaient bien sur le disque, aux bonnes dimensions +(96×96, cohérent avec le `texture_size` déclaré dans les modèles Blockbench `item//item`). +Un `Rebuild Project` complet n'y changeait rien — **ce n'était pas le piège `bin/main` du §2.2**, +malgré la ressemblance de symptôme (« le fichier est bon mais rien ne change en jeu »). + +**Divergence avec Forge, volontaire mais insuffisamment comprise au moment du portage.** +`CNBuilderTransformers.coloredArmorModel` (ligne ~50) fait pointer la texture des 16 modèles +colorés (`item/colored/_anti_radiation_.json`) directement vers +`createnuclear:models/armor/_anti_radiation_suit` — la même texture que celle utilisée +pour la couche d'armure portée sur le corps (via `AntiRadiationArmorTextureMixin` / +`ClothTagHelper`). Forge, lui, **duplique** ces 16 textures dans un second dossier, +`textures/item/armors/_anti_radiation_suit.png`, et c'est ce chemin dupliqué que pointe +son propre `CNBuilderTransformers`. Ce n'était pas une maladresse côté Forge : c'était nécessaire, +pour la raison ci-dessous — non documentée jusqu'ici, d'où sa redécouverte à la dure ici. + +**Cause réelle :** l'atlas `minecraft:blocks` (`textures/atlas/blocks.png`, celui qui fournit les +UV de tout modèle d'item 3D type Blockbench, par opposition aux icônes plates `item/generated`) +n'inclut par défaut que certains dossiers comme sources de sprites (`textures/block/`, +`textures/item/`, plus quelques ajouts `single` par mod). `textures/models/armor/` n'en fait +**jamais partie** côté vanilla — ce dossier est réservé aux textures de couche d'armure, chargées +par liaison GL directe (`HumanoidArmorLayer`), jamais par lookup d'atlas. D'où le warning : le +fichier existe, mais n'est simplement jamais stitché dans l'atlas que ces modèles 3D interrogent +pour leurs UV. + +**Correctif retenu ici (différent de Forge — sans dupliquer les textures) :** ajout de +`src/main/resources/assets/minecraft/atlases/blocks.json`, qui déclare `models/armor` comme +source `directory` supplémentaire de l'atlas `minecraft:blocks` : +```json +{ "type": "directory", "source": "models/armor", "prefix": "models/armor/" } +``` +Les sources de plusieurs packs de ressources pour un même atlas **s'additionnent**, elles ne +s'écrasent pas — donc sans risque pour les entrées `single` déjà présentes dans ce fichier +(sprites de fluides `thorium`/`uranium`/`nitrogen`). **Piège rencontré en l'écrivant, à surveiller +pour toute future entrée dans ce même fichier :** une première tentative avait imbriqué l'entrée +dans un objet sans son propre champ `"type"` (`{ "sources": [ { "type": "directory", ... } ] }` +au lieu de `{ "type": "directory", ... }` directement dans le tableau `"sources"` racine) — JSON +valide mais source non reconnue par le désérialiseur, qui a fait échouer le chargement de tout le +fichier et régresser au passage les sprites de fluides déjà fonctionnels. + +**Bug distinct trouvé au passage, corrigé dans le même lot :** les 4 modèles Blockbench de base +(`models/item/default_anti_radiation_{helmet,chestplate,leggings,boots}/item.json`) déclaraient +une texture par défaut (`layer0`/`particle`/`"14"` selon la pièce) pointant vers +`createnuclear:item/default_anti_radiation_suit` — un fichier qui n'a **jamais existé** dans ce +projet, ni côté Forge où le même chemin orphelin est présent à l'identique. Resté invisible côté +Forge (et côté NeoForge avant ce fix) parce que ces 4 modèles de base ne sont jamais bakés seuls : +ils ne servent que de `parent` aux 16 `overrides` colorés, qui redéfinissent systématiquement +leurs propres clés de texture — donc sans effet observable, mais une référence morte à nettoyer +si elle ressurgit un jour côté Forge. Corrigé en pointant vers +`createnuclear:models/armor/default_anti_radiation_suit`, qui existe réellement. + +--- + +## 4. Vérifications en jeu en attente + +Ce n'est pas du portage, mais c'est du travail restant. **Aucun de ces points n'est couvert par +les gametests.** + +| À vérifier | Attendu | Pourquoi c'est en attente | +|---|---|---| +| Comportement de la radiation | seuils, décroissance, persistance à la mort identiques à Forge | `RadiationCapability` diverge de 186 lignes. Le mécanisme (data attachments) est correct, mais rien ne dit que le comportement l'est | +| Tuyau ouvert Create crachant de l'uranium | irradie les entités de la zone | **testé, non concluant — reporté.** Aucune irradiation observée. Isolé en testant aussi lave (pose juste un bloc, jugé correct, pas de handler attendu) et thé (rien, non isolé). `CNOpenPipeEffectHandlers`/`RadiationEffectHandler` vérifiés identiques au bit près entre Forge et NeoForge — donc pas une divergence de portage si bug il y a. Piste non creusée : `RadiationCapability.canBeIrradiated()`, appelé par le handler, dépend de `CNConfigs.server().radiation.enabledItemRadiation`, un flag pensé pour la radiation passive par items et potentiellement mal réutilisé ici | +| Les 6 advancements réactivées (`anti_radiation_armor`, `avoiding_cancer`, `dye_anti_radiation_armor`, `feeding_the_reactor`, `fueling_the_reactor`, `unlimited_power`) | se débloquent au bon moment, en particulier `avoiding_cancer` (équiper les 4 pièces d'armure anti-radiation) dont le trigger a été réécrit | §3.4.1 corrigé sans test en jeu — vérifié uniquement par compilation + `runData` | + +> ✅ **Tooltip d'une barre d'uranium/graphite — testé en jeu, confirmé.** Cinq lignes de stats, +> type en vert (FUEL) ou cyan. Sorti de la liste des points en attente. +> +> ✅ **`raw_uranium_block` en inventaire — testé en jeu, confirmé.** La radiation monte bien de 27 +> par item. Sorti de la liste des points en attente. +> +> ✅ **Ventilateur derrière de la neige poudreuse — testé en jeu, confirmé.** Le concentré d'azote +> devient concentré refroidi, particules flocon/éternuement présentes, entités ralenties ; la +> catégorie JEI « Cryogenic fan » (§2.1/§3.4.3) est bien câblée. Sorti de la liste des points en +> attente. +> +> ✅ **`IrradiatedWolf` réaligné sur Forge — testé en jeu, confirmé.** Nourrir un loup non +> apprivoisé (yellowcake) affiche le message WIP au lieu de l'apprivoiser (§3.4.5). Sorti de la +> liste des points en attente. +> +> ✅ **Minage `uranium_ore`/`deepslate_uranium_ore`/`lead_ore`/`deepslate_lead_ore` — testé en jeu, +> confirmé.** Drop 3–4 (uranium) / 2–4 (plomb) de matière brute plus bonus fortune, conforme au +> correctif du §3.3. Sorti de la liste des points en attente. +> +> ✅ **`enable_world_gen` (false et true) — testé en jeu, les deux cas confirmés, mais un vrai bug +> trouvé et corrigé au passage.** `enable_world_gen = false` sur un monde neuf : aucun +> uranium/plomb/thorium/nitrate ni strate n'apparaît, le filtre `createnuclear:config_filter` +> fonctionne. `enable_world_gen = true` : les cinq features génèrent, mais **les valeurs de +> génération ne matchaient pas Forge** — corrigé côté joueur dans `CNConfiguredFeatures.java`/ +> `CNPlacedFeatures.java` : +> +> | Minerai | Avant (divergent) | Après (= Forge) | +> |---|---|---| +> | `URANIUM_ORE` count/hauteur | 7 / -63→16 | **4** / -63→16 | +> | `LEAD_ORE` taille de veine / count / hauteur | 10 / 10 / -16→112 | **12** / 10 / -16→**60** | +> | `THORIUM_ORE` taille de veine / count / hauteur | 16 / 16 / -16→112 | **12** / **6** / -16→**55** | +> | `STRIATED_ORES_OVERWORLD` rareté / hauteur | 1/18 / -30→70 | **1/64** / **-63→16** | +> +> `NITRATE_ORE` était déjà conforme (6 / -63→64), pas touché. Sorti de la liste des points en +> attente. +> +> ✅ **Chaîne complète de l'azote — testée en jeu, confirmé de bout en bout.** Nitrate → (four) → +> concentré → (ventilateur + neige poudreuse) → concentré refroidi → (mixeur + glace) → 100 mB +> d'azote liquide (§3.1). Sortie de la liste des points en attente. +> +> ✅ **`WolfPanicGoal` et `eyeHeight(0.68f)` — sortis de cette liste de vérifications, pas fermés +> par un test manuel isolé.** Décision du 16 août : une future passe couvrira le comportement de +> **toutes les living entities du mod** (pas seulement le chat comme en §2.1/§3.4.5) — `WolfPanicGoal` +> et la hauteur des yeux du loup seront revérifiés à cette occasion, avec le reste (goals IA, +> réductions de « copies » de mobs vanilla). Inutile de les tester isolément avant cette passe. +> +> **Divergence assumée sur la clé de config.** `CWorldGen` exposait `disableWorldGen` (défaut +> `false`) — un copier-coller littéral de la classe homonyme de Create, **jamais lu par personne**. +> Il est remplacé par `enable_world_gen` (défaut `true`), la clé de Forge. Un `createnuclear-common.toml` +> existant perdra donc son ancienne entrée : sans effet, puisqu'elle n'en avait aucun. + +--- + +## 5. Ordre de travail suggéré + +| # | Chantier | Fichiers | Difficulté | Pourquoi ce rang | +|---|---|---|---|---| +| 1 | **Audit `CNBlocks` / `CNItems` (§3)** | — | continu | À faire au fil des symptômes, pas d'un bloc | + +> ✅ **`getStandingEyeHeight` mort côté `IrradiatedCat`/`IrradiatedCow` (§3.4.5) — confirmé, mais +> volontairement sorti de cette liste.** Présent dans les deux fichiers (même override mort que +> celui trouvé et corrigé sur `IrradiatedWolf`). Une vraie passe d'intégration est prévue sur ces +> deux entités, avec pour but explicite de réduire au maximum les « copies » de mobs vanilla — +> corriger ce point isolément ici serait jeté à cette prochaine passe. **Ce n'est plus un chantier +> de parité Forge/NeoForge**, à traiter dans le cadre de ce futur refactor. + +> ✅ Audit ligne à ligne de `CNAdvancement`, `CNStandardRecipeGen`, `CreateNuclearJEI`, +> `RadiationCapability`, `IrradiatedWolf` (§3.4) — fait le 16 août : `CreateNuclearJEI` est sain +> (superset de Forge, catégorie snow-powder confirmée câblée). La divergence de persistance de +> `RadiationCapability` (§3.4.4) et les 6 recettes de décompactage en trop de +> `CNStandardRecipeGen` (§3.4.2) sont **assumées volontairement, closes** — pas de travail +> restant dessus. +> +> ✅ **`CNAdvancement` corrigé (§3.4.1)** — les 6 advancements désactivées ont été décommentées et +> réactivées ; `AVOIDING_CANCER` avait en plus un vrai piège 1.21 (`CriterionTrigger.getId()` +> disparu de l'API) résolu en reconstruisant le trigger via `CriteriaTriggers.INVENTORY_CHANGED +> .createCriterion(new InventoryChangeTrigger.TriggerInstance(...))`. Compile et `runData` passent ; +> non testé en jeu (§4). +> +> ✅ **`IrradiatedWolf` corrigé (§3.4.5)** — `WolfPanicGoal` réintroduite, apprivoisement/armure +> complet retiré et remplacé par le blocage WIP de Forge (`AnimalUtil.blockTamingWip`), +> `TAME_HEALTH` réaligné à `20.0F`, `canBeLeashed` réparé (appel à `super` manquant). Piège 1.21 +> trouvé au passage sur `getStandingEyeHeight` (override mort, hook disparu de l'API) — corrigé +> pour le loup via `EntityType.Builder.eyeHeight(...)`, mais probablement présent aussi côté +> `IrradiatedCat`/`IrradiatedCow` (chantier #1 ci-dessus). Compile et `runData` passent ; non +> testé en jeu (§4). +> +> ✅ Audit ligne à ligne complet de `CNBlocks`/`CNItems` (§3.3) — fait le 16 août : parité de +> liste confirmée (27 blocs, 29 items), les 6 `addLayer` « manquants » se sont révélés être un +> remplacement correct par `render_type` en JSON (pas un bug), et un vrai bug de rendement de +> minerai (uranium/plomb sans `set_count` de base) trouvé et corrigé. La ligne reste « continu » +> par nature (voir §3.3), mais cette passe-ci est close. +> +> ✅ Abstraction animaux — `IrradiatedAnimal` (§2.1) — commit `7d16431` du 16 août : interface +> portée, `IrradiatedChicken` l'implémente (comme côté Forge), poulet rattrapé sur ponte d'œufs/ +> chicken-jockey, `IrradiatedCat` réécrit pour suivre `Cat` vanilla. Dernier chantier de ce +> document, sorti de cette liste — plus rien à porter au niveau features. +> +> ✅ Namespace `create` des recettes crushing/washing (§3.1) — corrigé, commit `93975b3`, sorti de +> cette liste. +> +> ✅ `CNShapelessRecipeGen` (§2.2) — supprimé plutôt que rebranché (dead code depuis le début), +> commit `93975b3`, sorti de cette liste. +> +> ✅ `logoFile` (§2.2) — image déplacée de `META-INF/icon.png` vers `icon.png` (racine des +> resources), seul emplacement que NeoForge résout réellement pour cette clé. +> +> ✅ Vache irradiée + `AnimalUtil` (§2.1) — commit `5350638`. +> +> ✅ `IrradiatedWoldCollarLayer` (§2.2) — supprimée plutôt que branchée (dead code depuis le +> début), commit `4918bf7`, sorti de cette liste. +> +> ✅ Icônes d'inventaire des armures anti-radiation colorées (§3.2) — atlas `minecraft:blocks` +> manquait `models/armor` comme source de sprites ; corrigé le 15 août sans dupliquer les +> textures côté Forge, détail complet en §3.2. + +Les tests en jeu du §4 passent avant tout ça. + +--- + +## 6. Méthode de portage — ce qui a marché sur le réacteur + +À reprendre pour chaque chantier ci-dessus. + +1. **Chercher d'abord les classes NeoForge jamais référencées.** Voir l'encadré du §0 : deux + features sur deux se sont révélées présentes mais mortes, faute d'un point d'enregistrement. + Un `grep -rl src` qui ne renvoie que le fichier lui-même est un signal fort. +2. **Porter à l'identique par défaut.** Copier le fichier Forge, ne changer que ce que l'API + 1.21 impose. Sur le réacteur, ~35 fichiers sur 50 sont restés **identiques à l'octet**. +3. **Vérifier chaque fichier par un `diff`** contre son original Forge, et **justifier chaque + ligne qui diffère**. C'est ce qui a permis de garder les deux versions synchronisables. +4. **Compiler après chaque lot**, pas à la fin. +5. **Un commit par lot**, poussé avant d'enchaîner. +6. **Documenter toute divergence assumée** dans le commit, pour qu'une future synchro ne la + « corrige » pas par erreur. +7. **Tester en jeu.** Tout le portage du réacteur compilait et passait les gametests avant que + six bugs bien réels ne sortent au premier test manuel. + +### Pièges 1.20.1 → 1.21 déjà rencontrés + +| Forge 1.20.1 | NeoForge 1.21 | +|---|---| +| `net.minecraftforge.*` | `net.neoforged.neoforge.*` / `net.neoforged.api.*` | +| `ForgeRegistries.X.getKey(v)` | `BuiltInRegistries.X.getKey(v)` | +| `ForgeRegistries.X.getValue(rl)` | `BuiltInRegistries.X.getOptional(rl)` | +| `new ResourceLocation(s)` | `ResourceLocation.parse(s)` | +| `read/write(CompoundTag, boolean)` | `read/write(CompoundTag, HolderLookup.Provider, boolean)` | +| `ItemStack.of(tag)` | `ItemStack.parse(provider, tag)` → `Optional` | +| `stack.serializeNBT()` | `stack.saveOptional(provider)` | +| `stack.getOrCreateTag()` | **DataComponents** — pas d'équivalent mutable | +| `use(...)` → `InteractionResult` | `useItemOn(...)` → `ItemInteractionResult` | +| `NetworkHooks.openScreen(player, be, buf)` | `player.openMenu(be, buf)` | +| `isPathfindable(state, getter, pos, type)` | `isPathfindable(state, type)` | +| `@Mod.EventBusSubscriber(bus = Bus.FORGE)` | `@EventBusSubscriber` — le bus GAME est le défaut, et l'attribut `bus` est déprécié | +| `data//structures/` | `data//structure/` *(singulier)* | +| capabilities `getCapability(...)` | `level.getCapability(Capabilities.X.BLOCK, pos, ctx)` | +| `ForgeCatnipServices.FLUID_RENDERER` | `CatnipServices.FLUID_RENDERER` — typé ``, **cast requis** | +| `ProcessingRecipe` + `RecipeWrapper`/`ItemStackHandler` | `StandardProcessingRecipe` — plus de classe wrapper à écrire, `new SingleRecipeInput(stack)` suffit | +| `Codec.unit(...)` pour un `PlacementModifierType` | `MapCodec.unit(...)` — `PlacementModifierType#codec()` renvoie un `MapCodec` | +| `CatnipServices.REGISTRIES.getKeyOrThrow(...)` | `RegisteredObjectsHelper.getKeyOrThrow(...)` | + +### Deux pièges qui ne cassent pas la compilation + +Ce sont les plus coûteux : le code compile, ne lève rien, et se comporte mal. + +1. **`stack.get(DataComponents.CUSTOM_DATA).copyTag()` renvoie une copie.** Traduire + `stack.getOrCreateTag().putX(...)` littéralement produit une écriture **silencieusement + perdue**. Passer par un composant typé et `stack.set(...)`. + +2. **Un codec persistant qui peut refuser une valeur fait planter la sauvegarde du monde**, + pas l'écriture — donc très loin de la cause. **Valider les invariants en amont, pas dans le + codec.** Rencontré deux fois : + - `ExtraCodecs.POSITIVE_FLOAT` sur la chaleur, qui refusait `0.0`, valeur normale d'un + réacteur à l'arrêt ; + - `ItemStack.CODEC` sur un motif de réacteur, qui **refuse la stack vide** alors que le motif + fait 57 slots presque jamais tous remplis. **Réflexe 1.21 : pour un `ItemStack` qui peut + être vide, c'est `ItemStack.OPTIONAL_CODEC` / `OPTIONAL_STREAM_CODEC`, jamais les variantes + strictes.** + + > Ce second cas ne s'était pas vu aux gametests parce qu'ils **ne rechargent pas le monde** : + > l'erreur ne sortait que dans le log de `runGameTestServer`, à l'arrêt du serveur, pendant + > que « All tests passed » s'affichait juste au-dessus. **Lire le log, pas seulement le + > verdict.** + +### Noms qui masquent une classe vanilla + +Trois classes du mod portent volontairement le nom d'une classe vanilla, pour rester alignées +sur Forge : `CNArmorMaterials` (`net.minecraft.world.item.ArmorMaterials`), `CatLieOnBedGoal` et +`CatSitOnBlockGoal` (`net.minecraft.world.entity.ai.goal.*`). Les fichiers concernés importent +le package vanilla en wildcard — **sans danger**, parce qu'en Java une classe du même package +l'emporte sur un import à la demande, et qu'aucun de ces fichiers n'utilise la classe vanilla +homonyme. **Mais si l'un d'eux a un jour besoin de la version vanilla, il faudra la qualifier +complètement** — un `import` simple ne suffira pas. + +--- + +## 7. Audit ciblé — `content/multiblock/controller` (14 août 2026) + +Audit ligne à ligne demandé spécifiquement sur ce sous-dossier du domaine réacteur, malgré le +statut « porté et validé » de [`PORTAGE_REACTEUR.md`](PORTAGE_REACTEUR.md), pour vérifier que +ce statut tient toujours après les commits récents (« clean up dead imports/logic... after +RodType alignment », etc.). + +### 7.1 Parité des fichiers + +Les deux arborescences contiennent **exactement les 41 mêmes fichiers `.java`**, mêmes noms, +mêmes sous-dossiers (`consumable/`, `display/`, `manager/`, `service/`, `snapshot/`). Aucun +fichier Forge orphelin, aucun ajout NeoForge sans équivalent. Aucune classe du dossier n'a un +compte de référence à 0 ailleurs dans `src` — pas de piège du §0 ici. + +### 7.2 Divergences internes + +21 fichiers sur 41 diffèrent contre l'original Forge ; 20 sont identiques à l'octet. Les 21 +divergences se répartissent en : + +- **API 1.21 correctement anticipée** (la majorité) : data components à la place du NBT mutable + (`CNDataComponents.HEAT`, `ReactorBluePrintData`), `read/write(..., HolderLookup.Provider, ...)`, + `ItemStack.parse`/`saveOptional`, `BuiltInRegistries` à la place de `ForgeRegistries`, + `level.getCapability(Capabilities.ItemHandler.BLOCK, ...)`, `useItemOn`/`ItemInteractionResult`. + Plusieurs fichiers (`ReactorControllerBlockEntity`, `ReactorHeatUpdateCoordinator`, + `IReactorHeatUpdateCoordinator`, `PatternReader`) portent même des Javadoc **nouvelles** + expliquant explicitement pourquoi (copie défensive des `ItemStack` sous NeoForge notamment). +- **Cosmétique** : commentaires traduits en français (`ReactorInputManager`, + `ReactorAlarmManager` et leurs interfaces), espaces blancs. +- `manager/ReactorInputFluidManager.java` (~ligne 123) : alloue un `new VirtualReactorInputFluid()` + au lieu de réutiliser l'instance déjà créée quand `handlers` est vide. Micro-inefficacité sans + impact fonctionnel, pas un bug. + +**Conclusion sur ce sous-dossier : le statut « porté et validé » tient.** Aucune divergence +interne trouvée n'est une régression de logique métier. + +### 7.3 Bug trouvé le 14 août, corrigé depuis — hors dossier `controller` mais qui l'impactait directement + +En remontant l'usage de `rodType.ratio()` (appelé dans `ReactorHeatUpdateCoordinator`, +`calculateHeatBalance`) jusqu'à sa définition dans `api/multiblock/rods/RodType.java`, un bug +latent avait été repéré : `Builder.ratio` valait `null` par défaut au lieu de `() -> 1` comme +promis par la Javadoc de `build()`, exposant tout `RodType` construit sans `.ratio(...)` +explicite à une `NullPointerException` au premier calcul de heat balance. + +> ✅ **Corrigé.** Commit `970503b` (« fix(rods): default RodType.Builder.ratio to 1 to prevent +> an NPE on unset rods ») — `Builder.ratio` vaut désormais `private Supplier ratio = +> () -> 1;` (ligne 141), conforme à la Javadoc et au comportement Forge. Rien à faire de plus +> sur ce point. + +### 7.4 Point pré-existant relevé au passage (ni régression ni lié au portage) + +`ReactorControllerBlock.java` (~ligne 140 NeoForge, ~130 Forge) : `state.setValue(ASSEMBLED, false)` +— `setValue` renvoie un `BlockState` immuable qui n'est ni réassigné ni appliqué via +`level.setBlock(...)`. Code mort **identique des deux côtés**, donc pas une régression du +portage, mais probablement un bug fonctionnel réel (le flag `ASSEMBLED` ne semble jamais remis à +`false` par ce chemin). À vérifier en jeu séparément — hors périmètre de ce document qui ne +traite que des écarts Forge/NeoForge. + +--- + +## 8. Vérifier l'état à tout moment + +```bash +# Fichiers Forge sans équivalent NeoForge — doit en lister 6 (3 du §1.1, 3 du §1.2, 0 du §2) +cd ~/Documents/Ynov/Ydays +diff <(cd CreateNuclearForge/src && find . -name '*.java' | sort) \ + <(cd CreateNuclearNeoForge/src && find . -name '*.java' | sort) + +# Recettes présentes côté Forge et absentes côté NeoForge (§3.1) +# Les préfixes diffèrent : `recipes/` en 1.20.1, `recipe/` en 1.21 +diff <(cd CreateNuclearForge/src/generated/resources/data/createnuclear/recipes && find . -name '*.json' | sort) \ + <(cd CreateNuclearNeoForge/src/generated/resources/data/createnuclear/recipe && find . -name '*.json' | sort) + +# Recettes qui fuient dans le namespace de Create — doit être vide hors tags +find CreateNuclearNeoForge/src/generated/resources/data/create -name '*.json' + +# Écart interne d'un fichier partagé +diff CreateNuclearForge/src/main/java/.../X.java \ + CreateNuclearNeoForge/src/main/java/.../X.java + +# Classes NeoForge jamais référencées (le piège du §0) +cd CreateNuclearNeoForge && grep -rl '' src --include=*.java + +# Non-régression du réacteur — doit sortir en 0 des deux côtés +cd CreateNuclearNeoForge && ./gradlew runGameTestServer # 31 tests +cd CreateNuclearForge && ./gradlew runGameTestServer # 28 tests +``` diff --git a/PORTAGE_REACTEUR.md b/PORTAGE_REACTEUR.md new file mode 100644 index 0000000..79bbb5b --- /dev/null +++ b/PORTAGE_REACTEUR.md @@ -0,0 +1,725 @@ +# Portage du réacteur — Forge → NeoForge + +Comparaison `CreateNuclearForge` (branche `V2`) → `CreateNuclearNeoForge` (branche `V2-Reacteur`). +Périmètre : domaine réacteur uniquement (`content/multiblock/**` + dépendances directes). + +> ## ✅ Portage terminé et validé en jeu +> +> Les 8 lots sont faits. Le réacteur s'assemble, produit, chauffe, alarme, fond et explose. +> Validé en jeu par mathi le 6 août 2026 : assemblage, blueprint, fluide, production SU. +> +> **~50 fichiers portés**, dont la majorité identiques à l'octet à l'original Forge. +> `ReactorControllerBlockEntity` : 868 lignes monolithiques → 424 lignes déléguantes, +> divergence vs Forge ramenée de **864 lignes à 76** (toutes des adaptations 1.21). +> +> Gametests : `./gradlew runGameTestServer` → **31 tests, tous verts** (`EXIT=0`). +> Utilisable en CI bloquante. +> +> Ce qui reste hors périmètre est inventorié en **§9**. + +--- + +## 1. Constat central + +**Le réacteur NeoForge n'est pas une version « réorganisée » du réacteur Forge : c'est une génération antérieure du code.** + +C'est le point le plus important du rapport, parce qu'il change la nature du travail. Un portage classique consiste à traduire l'API. Ici, il faut d'abord **remplacer la logique**, puis traduire l'API. + +| | Forge | NeoForge | +|---|---|---| +| `ReactorControllerBlockEntity` | 440 lignes, logique déléguée | **735 lignes monolithiques** | +| Packages `service/`, `reactorLogic/`, `consumable/`, `snapshot/`, `display/` | 31 fichiers | **0 — inexistants** | +| Modèle thermique | équilibre 6:1 fuel/cooler, surchauffe progressive, fluide caloporteur | somme `baseUraniumHeat`/`baseGraphiteHeat` codée en dur | +| Fusion du cœur | compte à rebours 300 ticks + notifications + explosion dimensionnée | **absente** | +| Alarmes | pilotées par coordinateur + advancement | **jamais déclenchées** | +| Consommation des barres | cycles par type de barre, persistés en NBT | timers `tmpUraniumTimer`/`tmpGraphiteTimer` codés en dur | +| Son de fonctionnement | boucle pilotée par blockstate `ACTIVE` | **absent** | +| Tooltip goggles | rendu depuis un snapshot synchronisé | lit `fuelItem`/`coolerItem` locaux | + +Concrètement, le `tick()` NeoForge fait encore : lire l'inventaire d'un unique `ReactorRodInput`, décrémenter deux timers, calculer une chaleur par voisinage uranium/graphite, et faire tourner la sortie. Il n'y a ni surchauffe, ni fusion, ni explosion, ni consommation de fluide. + +**Conséquence sur la méthode :** ne pas essayer de « compléter » le BE NeoForge existant. Il faut le remplacer par la version Forge et porter les 31 fichiers de logique en dessous. Les ~300 lignes actuelles de calcul (`calculateHeat`, `calculateProgress`, `updateTimers`, `getStructureBounds`, `convertePattern`, `formattedPattern`, `rotate`) sont du code mort une fois le portage fait. + +--- + +## 2. Ce qui existe déjà côté NeoForge (bonne nouvelle) + +Toute l'infrastructure dont dépendent les services Forge est **déjà présente** : + +`RodType` · `ReactorFluidType` · `BigFluidStack` · `NotifyUtil` · `CreateNuclearLang` · `BiomeIrradiationService` · `CNBiomes` · `NuclearExplosionEntity` · `CNAdvancement` · `CNAdvancementBehaviour` · `CNConfigs` · `ReactorBluePrintItem.getItemStorage()` · `CNSoundEvents.REACTOR_RUNNING` + +Les 5 managers (`ReactorInputManager`, `ReactorOutputManager`, `ReactorInputFluidManager`, `ReactorAlarmManager`, `AbstractReactorIOManager`) sont eux aussi déjà portés et à jour. + +Le portage ne part donc pas de zéro : il porte sur la couche logique, pas sur les fondations. + +--- + +## 3. Divergences d'API bloquantes — ✅ TRAITÉ (résolu au Lot 0) + +Ces cinq points devaient être réglés avant de porter le moindre service, sinon rien ne compilait. +**Ils l'ont tous été au Lot 0** (§4) ; voir le récapitulatif en §3.6. + +### 3.1 `RodType` — ✅ RÉSOLU (déjà fait au Lot 0, constat obsolète) + +> **Ce constat n'est plus vrai.** Il décrivait l'état d'avant le Lot 0 (§4). Depuis, `RodType` +> NeoForge a été aligné sur Forge et les deux fichiers sont désormais **structurellement +> identiques** : même `record`, mêmes champs, même builder, même `ratio()`, mêmes prédicats. +> Vérifié le 14 août 2026 par lecture côte à côte des deux fichiers. + +| | Forge | NeoForge | +|---|---|---| +| Champ item | `Holder item` | `Holder item` — **identique**, pas de `HolderSet` | +| `baseRodHeat()` / `proximityRodHeat()` / `rodTimer()` | `Supplier` / `Supplier` / `Supplier`, appelés `.get()` | **identique** | +| `ratio()` | présent (`Supplier`, défaut `1`) | **présent**, identique | +| `TypeRodPredicate` | `isFuel(RodType)` / `isCooled(RodType)` + `isFuel(ItemStack, Level)` / `isCooled(ItemStack, Level)` | **identique**, les 4 surcharges sont là | + +Seules différences réelles restantes, purement cosmétiques : +- imports `net.neoforged.neoforge.registries.NeoForgeRegistries` / `BuiltInRegistries.ITEM.getKey(...)` (NeoForge) vs `net.minecraftforge.registries.ForgeRegistries` (Forge) dans `toString()` ; +- NeoForge importe `HolderSet` et `CNItemTags` sans s'en servir dans ce fichier (imports morts, à nettoyer un jour, sans impact fonctionnel). + +**Rien à faire** pour ce point : le §3.1 était un résidu documentaire d'avant le Lot 0, jamais corrigé après coup. + +### 3.2 `IHeat.HeatLevel` — ✅ RÉSOLU (déjà fait au Lot 0, constat obsolète) + +> **Ce constat n'est plus vrai**, même diagnostic que le §3.1. Vérifié le 14 août 2026 par +> lecture côte à côte des deux fichiers `IHeat.java`. + +| | Forge | NeoForge | +|---|---|---| +| `of(int heat, int reactorSize)` | présent, seuils lus dans `CReactorHeat` (`size5Danger`/`size7Danger`/`size9Danger`) | **identique** | +| `isNotDanger(int heat, int reactorSize)` | présent | **identique** | +| `getFormattedHeatText(int heat, int reactorSize)` | présent | **identique** | +| `getFormattedItemText(ItemStack, Boolean, Level)` | présent | **identique** | + +Les seuils de danger dépendent bien de la taille du réacteur (5×5 / 7×7 / 9×9) des deux côtés, +via la config `CReactorHeat` (§3.3, elle aussi déjà portée). Seule différence : Forge importe +`CNItemTags`, `ItemRodTypesValue` et `RodType` sans s'en servir dans ce fichier (imports morts +côté Forge cette fois, sans impact). + +**Rien à faire** pour ce point. + +### 3.3 `CReactorHeat` — ✅ RÉSOLU (déjà fait au Lot 0, constat obsolète) + +`infrastructure/config/CReactorHeat.java` existe côté NeoForge avec les 3 valeurs attendues, +identiques à Forge : + +```java +public final ConfigInt size5Danger = i(256, 0, 8192, ...); +public final ConfigInt size7Danger = i(1024, 0, 8192, ...); +public final ConfigInt size9Danger = i(4096, 0, 8192, ...); +``` + +Déclaré dans la config serveur, lu par `IHeat.HeatLevel.of()` (§3.2). **Rien à faire.** + +### 3.4 `CRods` — ✅ RÉSOLU (déjà fait au Lot 0, constat obsolète) + +`CRods` NeoForge expose désormais les 12 valeurs, uranium / graphite / **thorium** compris, +avec `*HeatRatio`, `*ProximityBonus`/`*ProximityMalus` et `*BaseValue` pour chacun — vérifié le +14 août 2026 par lecture du fichier. **Rien à faire.** + +### 3.5 `ReactorControllerBlock` — ✅ RÉSOLU (déjà fait au Lot 0, constat obsolète) + +`ACTIVE` (`BooleanProperty`) est bien déclarée à côté d'`ASSEMBLED`, ajoutée au `StateDefinition` +(`builder.add(FACING).add(ASSEMBLED).add(ACTIVE)`) et initialisée à `false` par défaut — vérifié +le 14 août 2026. **Rien à faire.** + +--- + +### 3.6 Récapitulatif — tout le §3 est résolu depuis le Lot 0 + +> **Historique.** Les 5 points ci-dessus (3.1 à 3.5) décrivaient l'état du repo **avant** le +> Lot 0 (§4). Le Lot 0, marqué ✅ FAIT, les a tous traités — mais le présent §3 n'avait jamais +> été mis à jour après coup pour le refléter, ce qui le rendait trompeur pour quiconque le lisait +> sans avoir aussi lu le §4. Vérifié fichier par fichier le 14 août 2026 (contre l'état courant de +> `CreateNuclearForge` branche `V2`) : + +| Point | Sujet | Statut | Fichier(s) vérifié(s) | +|---|---|---|---| +| 3.1 | `RodType` | ✅ résolu | `api/multiblock/rods/RodType.java` | +| 3.2 | `IHeat.HeatLevel` | ✅ résolu | `content/multiblock/IHeat.java` | +| 3.3 | `CReactorHeat` | ✅ résolu | `infrastructure/config/CReactorHeat.java` | +| 3.4 | `CRods` | ✅ résolu | `infrastructure/config/CRods.java` | +| 3.5 | `ReactorControllerBlock` (`ACTIVE`) | ✅ résolu | `content/multiblock/controller/ReactorControllerBlock.java` | + +Aucune divergence d'API bloquante ne subsiste sur ce périmètre. Les seuls écarts restants entre +les deux fichiers de chaque paire sont cosmétiques (imports `neoforged` vs `minecraftforge`, +quelques imports inutilisés d'un côté ou de l'autre). + +--- + +## 4. Fichiers à créer — par ordre de portage — ✅ TRAITÉ + +Tous les lots (0 à 9) sont marqués faits ci-dessous, et vérifiés fichier par fichier le +14 août 2026 (voir les encarts de vérification sous les Lots 0, 3/6). Il ne reste **rien à +porter** dans ce périmètre. + +> **Non re-testé en jeu.** Le portage lui-même a été validé en jeu par mathi le 6 août 2026 +> (bandeau en tête de document). Mais la correction du bug `ReactorAlarmManager` trouvée et +> appliquée le 14 août 2026 pendant cette passe de vérification (logique de `getBlocksPosition`/ +> `clearInvalid` qui était commentée, cf. Lot 6) est postérieure à cette validation et **n'a pas +> encore été testée en jeu** — seule une vérification statique (diff de code) a été faite. À +> tester : le déclenchement effectif des alarmes (`ReactorAlarm.POWERED`) quand un réacteur passe +> en `DANGER`. + +### Lot 0 — Prérequis (rien ne compile sans) ✅ FAIT +| Fichier | Note | +|---|---| +| `infrastructure/config/CReactorHeat.java` | création | +| `infrastructure/config/CRods.java` | **extension** (thorium + ratios + proximité) | +| `api/multiblock/rods/RodType.java` | **modification** (valeurs en `Supplier`, `ratio()`, prédicats `RodType`) | +| `content/multiblock/IHeat.java` | **modification** (seuils par taille) | +| `content/multiblock/controller/ReactorControllerBlock.java` | **modification** (`ACTIVE`) | +| `content/multiblock/controller/ReactorControllerGenerator.java` | **modification** (textures off/standby/on) | +| `CNItems.java` | **modification** — voir ci-dessous | + +> **Trouvé en cours de route :** seul `THORIUM_ROD` avait un `RodType` enregistré côté +> NeoForge. `URANIUM_ROD` et `GRAPHITE_ROD` n'en avaient aucun, donc `resolveRodType()` +> retombait sur `FALLBACK` (type `NONE`), que `DefaultHeatCalculator` ignore : le modèle +> thermique aurait calculé **zéro chaleur en permanence**, sans erreur visible. Les trois +> barres sont désormais enregistrées et adossées à la config. +> +> ⚠️ Le blockstate du contrôleur passe de 8 à 16 variants (ajout d'`ACTIVE`) : +> `runData` doit être relancé, sinon le bloc affiche un modèle manquant en jeu. + +### Lot 1 — Modèle thermique (`reactorLogic/`, 7 fichiers, ~217 lignes) ✅ FAIT +`IHeatCalculator` · `DefaultHeatCalculator` · `IOverheatController` · `DefaultOverheatController` · `HeatBalance` · `EquilibriumState` · `HeatManager` + +Cœur du modèle : équilibre 6:1 fuel/cooler, surchauffe qui s'accélère (`overFlowLimiter` décrémenté), pénalité de fluide insuffisant ou de dépassement du `maxHeat` du fluide. + +> **Correction d'ordre :** `display/ReactorDisplayState` est une dépendance dure de +> `DefaultHeatCalculator` (paramètre de `computeHeat`). Il a donc été porté avec le lot 1 +> au lieu du lot 4. Ses méthodes NBT prennent un `HolderLookup.Provider` en 1.21, parce que +> `BigFluidStack.write()/read()` l'exigent côté NeoForge. + +### Lot 2 — Lecture de pattern & consommation (`consumable/`, 6 fichiers, ~317 lignes) ✅ FAIT +`PatternReader` · `IConsumable` · `ItemConsumable` · `FluidConsumable` · `ConsumableTimer` · `ConsumptionCycleManager` + +`PatternReader` est utilisé par le lot 1 et le lot 3 — à porter tôt. + +> **Divergence corrigée dans `ReactorBluePrintMenu` :** côté Forge, `pattern` est la grille +> brute du joueur et `patternAll` la **même grille normalisée** — slots vides *et* items +> non-barres remplacés par du `GLASS_PANE`. Côté NeoForge les deux champs pointaient sur +> **le même tableau**, et les items non-barres y étaient conservés. +> +> Sans correction, un item quelconque déposé dans la grille aurait été compté par +> `PatternReader` comme une exigence du pattern. `ReactorHeatUpdateCoordinator.updateHeatOnly` +> exige que *chaque* entrée du pattern soit disponible dans les inputs : un item non-barre +> n'étant jamais fourni, la chaleur serait restée bloquée à 0 sans erreur visible. +> +> `saveData` construit désormais deux tableaux distincts. `getItemStorage()` continue de lire +> `pattern()` (brut), comme la version Forge qui lit l'élément NBT `pattern`. + +#### Lot 2bis — Migration NBT → Data Components du blueprint ✅ FAIT (9 août 2026) + +Le lot 2 ci-dessus portait la lecture du pattern ; ce qui suit va plus loin et retravaille le +**stockage** du blueprint lui-même (`bluePrintItem/`), au-delà d'un simple portage d'API. + +**Point de départ.** À l'ouverture de ce chantier, le blueprint NeoForge était dans un état +intermédiaire : `ReactorBluePrintData`/`PatternData` (les vrais Data Components) coexistaient +avec des restes NBT jamais nettoyés après leur introduction — un composant +`CNDataComponents.PATTERN` qui ne faisait que réemballer une `CompoundTag` (jamais écrit, +toujours lu vide), un paquet réseau (`ReactorBluePrintItemPacket`) hérité du portage Forge dont +**tous les champs étaient write-only** côté client (`heat`, compteurs, `progress`, +`sendUpdate` : aucun n'était relu par un rendu ou une logique quelconque), et quatre Data +Components orphelins (`URANIUM_TIME`, `GRAPHITE_TIME`, `COUNT_GRAPHITE_ROD`, +`COUNT_URANIUM_ROD`) enregistrés mais jamais lus ni écrits. + +**Ce qui a été fait :** +- Suppression complète du paquet réseau et de son enregistrement dans `CNPackets` : ce menu + n'a structurellement besoin d'aucun paquet, dans aucun sens. C'est un menu à un seul joueur + possible (item tenu en main), l'édition du pattern passe déjà par la synchronisation de slots + vanilla, et `saveData()` (`MenuBase#removed`, dans Create) écrit directement sur le + `contentHolder` serveur sans aller-retour réseau. +- Suppression de `CNDataComponents.PATTERN` et des quatre composants orphelins. +- `ReactorBluePrintData` réduit à `(int countCooledRod, int countFuelRod, PatternData[] pattern)` : + `patternAll` n'est plus persisté ni synchronisé, il est dérivé à la demande + (`patternAll(Level)`) depuis `pattern`, ce qui élimine par construction le risque de + divergence entre les deux vues qui avait motivé la correction du lot 2. `graphiteTime`/ + `uraniumTime` sont retirés aussi : ce n'étaient que des constantes de config recopiées sur + chaque blueprint, jamais lues nulle part. +- Ajout d'un sentinel `ReactorBluePrintData.EMPTY`, qui remplace sept réimplémentations + indépendantes de « ce blueprint est-il configuré ? » (`configuredPattern.get(...) == null`, + dupliqué dans `ReactorControllerBlockEntity` ×4, `ReactorControllerBlock`, + `ReactorHeatUpdateCoordinator`, `ConsumptionCycleManager`) par un seul point de vérité, + comparé par identité (`== EMPTY`), sur le même principe que `ItemStack.EMPTY`. + +**Bug trouvé et corrigé, propre à NeoForge :** un blueprint contenant des barres de thorium +perdait silencieusement ces barres à la réouverture du menu (confirmé par un dump NBT +`/setblock` montrant le pattern correctement sauvegardé, mais absent une fois le menu rouvert). +Cause : `THORIUM_ROD` est enregistré `.fuelRodType()` côté `RodType` (`CNItems.java`), mais son +`.tag(...)` n'incluait pas `CNItemTags.FUEL.tag` — contrairement à `URANIUM_ROD`/`GRAPHITE_ROD`, +qui ont bien leur tag. `ReactorBluePrintMenu#initAndReadInventory` filtrait la réaffichage sur +ce tag plutôt que sur `RodType`, donc le thorium passait la sauvegarde mais échouait +silencieusement à la relecture. Corrigé à deux niveaux : le tag manquant ajouté dans +`CNItems.java`, et le filtre de réaffichage réécrit pour utiliser `RodType`/`TypeRodPredicate` +partout (comptage, `pattern`, `patternAll`, réaffichage), la même source de vérité que +`saveData` utilisait déjà pour `patternAll`. + +**Bug de config trouvé au passage, sans lien avec les Data Components :** `CNCCommon` déclarait +sa propre instance de `CRods` (`Type.COMMON`), en plus de celle déjà présente dans `CNCServer` +(`Type.SERVER`) — deux fichiers de config distincts pour la même donnée conceptuelle. Absent +côté Forge, où `CRods` ne vit que dans le config serveur. `ReactorBluePrintMenu` lisait la +copie `COMMON`, `RodType`/`CNItems` la copie `SERVER` : un admin modifiant l'une sans l'autre +aurait désynchronisé silencieusement la durée de vie affichée sur le blueprint de celle +réellement utilisée par le calcul de chaleur. Le champ dupliqué a été retiré de `CNCCommon`, +`ReactorBluePrintMenu` lit désormais `CNConfigs.server().rods`, comme le reste du code. + +> **Différence assumée entre Forge et NeoForge, à ne pas « corriger » lors d'une synchro.** +> Forge stocke le blueprint en NBT brut sur l'`ItemStack` (`getOrCreateTag().put("pattern", ...)`). +> NeoForge le stocke en Data Component typé (`ReactorBluePrintData`, `Codec` + `StreamCodec`). +> Ce n'est pas un écart à réduire : NBT muté en place sur un `ItemStack` casse silencieusement +> en 1.21 (voir §5.1, `copyTag()` renvoie une copie défensive), et les Data Components sont la +> direction que 1.21 impose pour ce genre de donnée structurée. Une synchro Forge → NeoForge sur +> `bluePrintItem/` ne doit **jamais** réintroduire de `CompoundTag`/`getOrCreateTag()` ; elle doit +> traduire chaque nouveau champ NBT Forge en champ du record `ReactorBluePrintData`, avec son +> propre `Codec`/`StreamCodec`, sur le modèle de `PatternData`. +> +> Différence secondaire assumée : le paquet réseau `ReactorBluePrintItemPacket` que Forge +> utilise n'a pas d'équivalent côté NeoForge, par choix, pas par oubli — voir le lot 2bis +> ci-dessus. S'il réapparaît un jour côté Forge avec un vrai usage (affichage de statistiques), +> ne pas le traduire tel quel : passer par la synchronisation de menu vanilla +> (`ContainerData`/`DataSlot`) plutôt que par un paquet personnalisé. + +**Ce qu'il reste, honnêtement :** aucun bug connu à ce stade sur `bluePrintItem/` après cette +passe. + +> **Précision (14 août 2026) sur la cause du bug thorium ci-dessus.** `fuelRodType()` et le tag +> `CNItemTags.FUEL` sont deux choses indépendantes par design — rien n'exige qu'un `RodType` +> classé `FUEL` porte ce tag. Confirmé côté Forge : `THORIUM_ROD` (`CNItems.java`) porte bien les +> deux (`.fuelRodType()` **et** `.tag(CNTags.forgeItemTag("rods"), CNItemTags.FUEL.tag)`), mais +> `TypeRodPredicate.isFuel()` — identique dans les deux repos (§3.1) — ne regarde que +> `RodType.resolveRodType(...).type`, jamais le tag. Même sur la version de référence, les deux ne +> sont donc pas couplés fonctionnellement. Le tag manquant sur `THORIUM_ROD` côté NeoForge n'était +> pas un oubli de règle du domaine, juste un oubli ponctuel pendant la migration du blueprint vers +> les Data Components (le thorium n'avait pas encore été aligné sur `URANIUM_ROD`/`GRAPHITE_ROD` à +> ce moment-là). Le vrai fix, celui qui compte, est la réécriture du filtre de +> `ReactorBluePrintMenu#initAndReadInventory` pour utiliser `RodType`/`TypeRodPredicate` au lieu du +> tag — l'ajout du tag manquant n'était qu'un correctif de circonstance, pas un invariant à garder. +> **Un gametest générique du style « tout `RodType` fuel doit avoir le tag FUEL » n'aurait donc pas +> de sens** et n'est plus recommandé ici. + +### Lot 3 — Services (`service/`, 12 fichiers sur 14) ✅ FAIT +`IHeatService` / `DefaultHeatService` · `IExplosionService` / `ReactorMeltdownExecutor` · `IReactorMeltdownMonitor` / `ReactorMeltdownMonitor` · `IReactorAlarmCoordinator` / `ReactorAlarmCoordinator` · `IReactorHeatUpdateCoordinator` / `ReactorHeatUpdateCoordinator` · `IFluidConsumptionRateCalculator` / `FluidConsumptionRateCalculator` + +> **Le piège de §5.1 est neutralisé.** `CNDataComponents.HEAT` (`DataComponentType`) +> **existait déjà** côté NeoForge — inutile d'en créer un. `ReactorHeatUpdateCoordinator` +> écrit désormais via `configuredPattern.set(CNDataComponents.HEAT, (float) heat)`, dans une +> méthode `writeHeat()` dédiée, au lieu de muter `getOrCreateTag()`. Le test de pattern vide +> passe par `isEmptyPattern()`, qui vérifie l'absence de `ReactorBluePrintData`. +> +> Hors javadoc, ce sont les **seules** différences avec l'original Forge : 9 des 10 autres +> fichiers sont identiques à l'octet. + +> **Reporté au lot 6 :** `IPersistenceService` et `DefaultPersistenceService`. Ils appellent +> des accesseurs que le `ReactorControllerBlockEntity` NeoForge actuel n'a pas encore +> (`setMultiblockFacing(Direction)` vs `String`, `getMultiblockPos()` en `BoundingBox` vs +> `int[]`, `serializeInventory`, `get/setDisplayState`). Les porter maintenant obligerait à +> réécrire le BE, c'est-à-dire à faire le lot 6 — ils partiront donc avec lui. + +### Lot 4 — Affichage & snapshot (6 fichiers, ~450 lignes) ✅ FAIT +`snapshot/ReactorInputSnapshot` · `snapshot/ReactorInputSnapshotBuilder` · `display/ReactorDisplayState` (porté au lot 1) · `display/ReactorGoggleTooltipRenderer` · `manager/ReactorFrameDisplayManagerI` · `manager/ReactorFrameDisplayManager` + +`ReactorFrameDisplayManager` remplace les champs `frameFluidCache*` / `frameColumn*` actuellement inlinés dans le BE NeoForge — c'est une extraction, la logique existe déjà et est équivalente. Le BE ne sera débarrassé de ses copies qu'au lot 6. + +> Aucune surprise sur ce lot : `ReactorInputSnapshot` est identique à l'octet, les trois +> autres ne diffèrent que par les imports `minecraftforge` → `neoforged`, plus +> `FluidStack.getDisplayName()` → `getHoverName()` dans le renderer. +> +> Le javadoc d'exemple de `ReactorGoggleTooltipRenderer` a été corrigé au passage : côté +> Forge il montrait un appel à `render()` avec 4 arguments alors que la méthode en prend 5. + +### Lot 5 — Divers contrôleur (2 fichiers, ~100 lignes) ✅ FAIT +`ReactorRunningSoundInstance` · `ReactorDebugDiagnostics` + +> Les deux fichiers sont **identiques à l'octet** — aucune adaptation d'API. `AbstractTickableSoundInstance` +> n'a pas bougé entre 1.20.1 et 1.21, et `ReactorAlarmSoundInstance` (déjà porté) sert de témoin. +> +> En revanche les 8 clés `createnuclear.reactor.debug.*` manquaient dans +> `lang/default/reactor.json` — ajoutées. Les 9 clés `notification.reactor.*` dont dépend le +> `ReactorMeltdownMonitor` du lot 3, elles, existaient déjà. `runData` est nécessaire pour +> répercuter les nouvelles clés dans `en_us.json`. + +### Lot 6 — Réécriture du block entity ✅ FAIT (lot 7 inclus) +`ReactorControllerBlockEntity` passe de **868 lignes monolithiques à 424 lignes** qui délèguent +aux 33 fichiers des lots 0-5. Divergence vs Forge : **864 lignes → 76**, toutes des adaptations +1.21 (`HolderLookup.Provider`, DataComponents, imports `neoforged`). + +Fichiers portés avec : `ReactorControllerBlock` · `ReactorAssembler` · `CNMultiblock` · +`ReactorPattern` · `MultiblockHelpers` · `ReactorOutput` · `ReactorOutputEntity` · +`ReactorOutputManager(I)` · `ReactorFrame` · `ReactorFrameRenderer` · `ReactorCasing` · +`ReactorCooler` · `ReactorCoreEntity` · `ReactorRodInput` · `IPersistenceService` / +`DefaultPersistenceService` · `IMultiblockController` (lot 7). + +> **Features réellement absentes de NeoForge, découvertes en câblant :** +> +> 1. **Seul le réacteur 5×5 existait.** `CNMultiblock` n'enregistrait qu'un multiblock, avec +> entrée et sortie à positions fixes. Forge en enregistre trois (5×5 / 7×7 / 9×9) où les I/O +> se placent librement sur l'enveloppe. Les 7×7 et 9×9 étaient donc **impossibles à assembler**. +> 2. **`ReactorFrameEntity` n'était jamais enregistré.** La classe et son renderer existaient, +> mais sans `BlockEntityEntry` dans `CNBlockEntityTypes` : le bloc frame n'avait aucune block +> entity, donc le rendu du fluide dans les vitres ne pouvait pas fonctionner. Ajouté. +> 3. **La capacité de fluide était multipliée par le nombre d'entrées.** `applyReactorTierCapacity` +> donnait à *chaque* entrée la capacité totale du réacteur ; 4 entrées = 4× la capacité prévue. +> Remplacé par `applyCapacity(int)`, l'assembleur répartissant le total comme sur Forge. +> 4. **`ReactorOutputEntity` utilisait un `KineticScrollValueBehaviour`** (vitesse réglable à la +> molette) au lieu du `generatedSpeed` persisté piloté par le manager. Remplacé, ce qui +> supprime aussi l'interaction `DIR` sur `ReactorOutput` que Forge avait retirée. +> +> **Piège évité :** Forge déclare `int heat = ...` dans `tick()` en variable **locale masquant le +> champ** — donc morte. Une lecture rapide pousse à en faire une affectation du champ, ce qui +> changerait la valeur de `previousHeat` passée au calcul. La sémantique Forge est conservée. + +**Divergences résiduelles assumées** (à ne pas « corriger » lors d'une synchro) : +`CNShapes.REACTOR_INPUT` et `CNBlockEntityTypes.REACTOR_INPUT` gardent leur nom NeoForge +(Forge : `REACTOR_ROD_INPUT`) — les renommer changerait l'identifiant de registre +`createnuclear:reactor_input` et casserait les mondes existants. + +> **Re-vérifié le 14 août 2026**, diff réel (pas juste lecture) des 6 fichiers directement dans +> `content/multiblock/controller/` (hors sous-packages, couverts séparément juste en dessous) : +> +> | Fichier | Verdict | +> |---|---| +> | `ReactorControllerBlock.java` | diff API seulement (`InteractionResult`→`ItemInteractionResult`/`useItemOn`, NBT→`CNDataComponents.HEAT`/`ReactorBluePrintData`, cf. différence assumée §2bis) | +> | `ReactorControllerBlockEntity.java` | diff API seulement (`HolderLookup.Provider` sur `read`/`write`/`serializeInventory`, mêmes accès DataComponents, + javadoc ajoutée) — aucune divergence de logique | +> | `ReactorControllerGenerator.java` | diff import seul (`neoforged` vs `minecraftforge`) | +> | `ReactorControllerInventory.java` | **diff** : `isItemValid` réécrit en `switch` (`case 0 -> CNItems.REACTOR_BLUEPRINT.isIn(resource); default -> !super.isItemValid(...)`) au lieu du `slot == 0 && resource.is(...)` de Forge. La branche `default` est inatteignable en pratique (l'inventaire n'a qu'1 slot, `super(1, be, 1, false)`), donc le comportement observable reste identique — mais c'est une réécriture, pas un simple renommage d'import, donc listé comme diff et pas comme "identique". | +> | `ReactorDebugDiagnostics.java` | **identique à l'octet** | +> | `ReactorRunningSoundInstance.java` | **identique à l'octet** | +> +> Les chiffres « 864 lignes → 76 » plus haut datent du Lot 6 lui-même et ne sont plus à jour +> (les deux fichiers ont grossi depuis, notamment avec le Lot 2bis) : le diff réel aujourd'hui +> est de 95 lignes changées sur 536 (Forge) / 580 (NeoForge) lignes. La **nature** de la +> divergence reste la même — uniquement des adaptations d'API 1.21, aucune logique métier +> différente — donc aucune action requise, seul le chiffre exact était devenu obsolète. +> +> **Scan complémentaire des sous-packages `consumable/`, `display/`, `manager/`, `service/`, +> `snapshot/`** (mêmes fichiers présents des deux côtés, aucun manquant) : +> +> | Sous-package | Fichiers identiques à l'octet | Fichiers en diff API/design seulement | +> |---|---|---| +> | `consumable/` | `ConsumableTimer`, `FluidConsumable`, `IConsumable`, `ItemConsumable` | `ConsumptionCycleManager`, `PatternReader` (réécrit pour lire `ReactorBluePrintData`, conforme à §5.1) | +> | `display/` | — | `ReactorDisplayState`, `ReactorGoggleTooltipRenderer` (imports + javadoc, cf. lot 4) | +> | `manager/` | `AbstractReactorIOManager`, `ReactorIOManager`, `ReactorOutputManager`, `ReactorOutputManagerI` | `ReactorAlarmManager(I)`, `ReactorFrameDisplayManager(I)`, `ReactorInputFluidManager(I)`, `ReactorInputManager(I)` | +> | `service/` | `FluidConsumptionRateCalculator`, `IExplosionService`, `IFluidConsumptionRateCalculator`, `IHeatService`, `IReactorAlarmCoordinator`, `IReactorMeltdownMonitor`, `ReactorAlarmCoordinator`, `ReactorMeltdownExecutor`, `ReactorMeltdownMonitor` | `DefaultHeatService`, `DefaultPersistenceService`, `IPersistenceService`, `IReactorHeatUpdateCoordinator`, `ReactorHeatUpdateCoordinator` | +> | `snapshot/` | `ReactorInputSnapshot` | `ReactorInputSnapshotBuilder` | +> +> Toutes ces diffs sont des adaptations d'API/design déjà couvertes ailleurs dans ce rapport +> (§5.2, §5.1/Lot 2bis). +> +> ⚠️→✅ **Bug trouvé puis corrigé pendant cette vérification (14 août 2026) :** +> `ReactorAlarmManager.getBlocksPosition(Level)` avait toute sa logique de filtrage commentée côté +> NeoForge (l'import de `ReactorAlarmEntity` était commenté aussi, alors que la classe existe bien +> dans les deux repos — ce n'était donc pas un problème de dépendance manquante), et renvoyait +> systématiquement une liste vide. `clearInvalid()` était cassée pareil. Conséquence : dans +> `ReactorAlarmCoordinator.update()` (`service/ReactorAlarmCoordinator.java` ligne 33), la boucle +> qui pose `ReactorAlarm.POWERED` sur les blocs d'alarme quand le réacteur passe en `DANGER` ne +> s'exécutait jamais — les alarmes ne se déclenchaient jamais en jeu, quel que soit le niveau de +> chaleur. Re-diffé après correction : les deux méthodes sont maintenant décommentées et actives +> des deux côtés ; seuls écarts restants, un commentaire traduit en français côté NeoForge et deux +> commentaires supprimés — cosmétique, aucun impact fonctionnel. + +### Lot 9 — Corrections issues du test en jeu ✅ FAIT + +Six défauts trouvés en jouant, tous corrigés. Cinq étaient des divergences NeoForge +préexistantes, un était une erreur introduite par le portage. + +| Symptôme en jeu | Cause | Origine | +|---|---|---| +| Crash à la sauvegarde du monde | `CNDataComponents.HEAT` en `ExtraCodecs.POSITIVE_FLOAT`, qui refuse `0.0` — or un réacteur à l'arrêt écrit 0 à chaque tick | **introduit au lot 3** | +| Fluide quasi noir dans les vitres | `reactor_frame` sans `.noOcclusion()` : bloc traité comme opaque plein, la lumière ne passe plus | préexistant | +| idem | renderer passant un `FluidState` au lieu du `FluidStack`, ce qui perd la teinte | introduit au lot 6 | +| 2 slots dans le rod input | `super(2)` avec uranium/graphite figés, au lieu d'un slot acceptant toute barre via `RodType` | préexistant | +| Explosion malgré un pattern stable | azote liquide **commenté** dans `CNReactorFluidTypes` → pas de `ReactorFluidType` → `efficiency = -1` → `fluidMalus` permanent → surchauffe infinie | préexistant | +| 81 920 SU au lieu de 512 000 | capacité de stress du `REACTOR_OUTPUT` à `10240.0` au lieu de `64000.0` (rapport 6,25 ✓) | préexistant | + +> **Leçon sur les codecs :** un codec **persistant** qui peut refuser une valeur échoue au moment +> de la **sauvegarde**, très loin de l'écriture fautive, et emporte le block entity avec lui. +> Les invariants de domaine se valident en amont, pas dans le codec. +> Le test `heatComponent_atZero_survivesSerialization` verrouille ce cas. + +**Trouvé en vérifiant :** Forge a **5 appels à `addLayer`**, NeoForge n'en avait qu'**un**. +Quatre blocs avaient perdu leur couche de rendu — dont `reinforced_glass` en `translucent`, +qui rendait donc **opaque**. Tous rétablis. + +--- + +## 5. Pièges de traduction 1.20.1 Forge → 1.21 NeoForge + +> **Nature différente des §3/§4 : ceci est un guide de référence, pas une checklist.** Rien à +> « clôturer » au sens propre — ces trois pièges restent vrais et utiles pour tout futur travail +> de synchro Forge → NeoForge. Vérifié le 14 août 2026 que l'état actuel du code les respecte : +> - **§5.1** : l'Option B recommandée est bien implémentée. `CNDataComponents.HEAT` existe et +> `ReactorControllerBlockEntity.getConfiguredPatternHeat()` le lit ; `PatternReader` a bien été +> réécrit pour lire `ReactorBluePrintData` plutôt que du NBT brut (confirmé lors du scan des +> sous-packages en §4/Lot 6). Le piège est neutralisé dans le code actuel — `getConfiguredPatternTag()` +> existe encore et renvoie toujours une copie défensive, mais plus rien ne le mute : c'est un +> vestige inoffensif, pas un risque actif. +> - **§5.2/§5.3** : tables de correspondance mécanique, toujours appliquées correctement partout +> où on les a croisées pendant les vérifications précédentes (§3, §4). Aucune action requise ; +> aucun changement de code fait dans cette section, donc pas de « pas encore testé en jeu » à +> signaler ici. + +### 5.1 ⚠️ Le piège majeur : `getConfiguredPatternTag()` renvoie une copie + +Côté Forge, la chaleur est **écrite dans le tag de l'ItemStack** : + +```java +configuredPattern.getOrCreateTag().putDouble("heat", heat); // mute en place +``` + +Côté NeoForge, l'implémentation actuelle est : + +```java +public CompoundTag getConfiguredPatternTag() { + return this.configuredPattern + .getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY) + .copyTag(); // ⚠️ COPIE +} +``` + +`copyTag()` renvoie une copie défensive. **Tout `put*` dessus est silencieusement perdu.** Traduire `ReactorHeatUpdateCoordinator.updateHeatOnly()` / `calculateAndWriteHeat()` littéralement produirait un réacteur dont la chaleur reste bloquée à 0, sans aucune erreur de compilation ni exception à l'exécution. + +Deux options : + +- **A — pansement** : après modification, réécrire le composant + `stack.set(DataComponents.CUSTOM_DATA, CustomData.of(tag))`. + Rapide, mais conserve la sémantique « NBT brut » que 1.21 cherche à supprimer. +- **B — propre (recommandé)** : introduire un `ReactorHeatData` (ou étendre `ReactorBluePrintData`, qui existe déjà comme record côté NeoForge) et remplacer les accès `tag.getDouble("heat")` par un accès typé. + +Option B est plus de travail mais s'aligne sur la direction déjà prise par le repo NeoForge, qui utilise `CNDataComponents` / `ReactorBluePrintData` / `PatternData`. Mélanger les deux approches est le vrai risque : `PatternReader` (Forge) lit `tag.getCompound("patternAll")`, alors que NeoForge stocke déjà le pattern dans `ReactorBluePrintData.patternAll()` sous forme de `PatternData[]`. + +**→ `PatternReader` ne doit pas être traduit ligne à ligne. Il doit être réécrit pour lire `ReactorBluePrintData`.** + +### 5.2 Correspondances mécaniques + +| Forge 1.20.1 | NeoForge 1.21 | +|---|---| +| `net.minecraftforge.items.IItemHandler` | `net.neoforged.neoforge.items.IItemHandler` | +| `net.minecraftforge.fluids.FluidStack` | `net.neoforged.neoforge.fluids.FluidStack` | +| `net.minecraftforge.api.distmarker.OnlyIn` | `net.neoforged.api.distmarker.OnlyIn` | +| `ForgeRegistries.ITEMS.getKey(item)` | `BuiltInRegistries.ITEM.getKey(item)` | +| `ForgeRegistries.ITEMS.getValue(rl)` | `BuiltInRegistries.ITEM.get(rl)` | +| `new ResourceLocation(s)` | `ResourceLocation.parse(s)` | +| `read/write(CompoundTag, boolean)` | `read/write(CompoundTag, HolderLookup.Provider, boolean)` | +| `handler.deserializeNBT(tag)` | `handler.deserializeNBT(provider, tag)` | +| `ItemStack.of(tag)` | `ItemStack.parse(provider, tag)` → `Optional` | +| `stack.serializeNBT()` | `stack.saveOptional(provider)` | +| `CODEC.encodeStart(..).getOrThrow(false, X::new)` | `CODEC.encodeStart(..).getOrThrow()` | + +`ReactorDisplayState` et `DefaultPersistenceService` concentrent la majorité de ces changements, car ils sérialisent tout. + +### 5.3 `FluidStack` n'est plus nullable de la même façon + +En 1.21, `FluidStack` porte des `DataComponents` et `FluidStack.EMPTY` se compare avec `isEmpty()`, jamais avec `==`. Le code Forge de `ReactorFrameDisplayManager` fait `fluid.isEmpty()` — correct — mais `stack.copy()` conserve désormais les composants, ce qui est le comportement voulu. + +--- + +## 6. Volumétrie + +| Lot | Fichiers | Lignes (Forge) | Difficulté | +|---|---|---|---| +| 0 — Prérequis | 5 (2 créés, 3 modifiés) | ~150 | moyenne | +| 1 — reactorLogic | 7 | 217 | faible (logique pure, peu d'API MC) | +| 2 — consumable | 6 | 317 | **élevée** (`PatternReader` à réécrire) | +| 3 — service | 14 | 536 | moyenne (persistence = élevée) | +| 4 — display/snapshot | 6 | 450 | **élevée** (sérialisation) | +| 5 — divers | 2 | 100 | faible | +| 6 — BlockEntity | 1 | 440 | **élevée** | +| 7 — api multiblock | 1 | ~30 | faible | +| **Total** | **42** | **~2 240** | | + +Les lots 1, 3 et 5 sont essentiellement de la traduction d'imports. Les lots 2, 4 et 6 demandent de vraies décisions d'architecture (DataComponents vs NBT). + +--- + +## 7. Recommandation d'ordre d'exécution + +1. **Lot 0** — sans lui rien ne compile. +2. **Décision DataComponents vs NBT** (§5.1) — elle conditionne les lots 2, 4 et 6. À trancher avant d'écrire une ligne du lot 2. +3. **Lots 1 → 5** dans l'ordre, en compilant après chaque lot. +4. **Lot 6** en dernier : le BE ne compile qu'une fois toutes ses dépendances présentes. +5. **Lot 7** au choix, indépendant. + +Les deux gametests Forge (`DefaultHeatCalculatorGameTest`, `ReactorInputFluidManagerGameTest`) sont à porter avec les lots 1 et 3 respectivement : ils valident précisément la logique la plus risquée. + +### Lot 8 — Gametests ✅ FAIT + +`./gradlew runGameTestServer` — **31 tests, tous verts** (`EXIT=0`, re-confirmé le 14 août 2026). + +Les 4 tests du modèle thermique passent, dont `threeByThreeDiamond` croisé avec le calculateur +du wiki communautaire. C'est la première validation à l'exécution du portage. + +> À l'écriture du lot, la suite comptait 31 tests dont 2 échouant volontairement : les marqueurs +> `*_expectedContract` du bug `extractFluids`, qui échouait identiquement sur Forge. Ce bug est +> corrigé depuis dans les deux repos (§9.4), les marqueurs sont donc passés au vert et les deux +> tests qui figeaient le comportement bogué ont été supprimés — ramenant la suite à 29. Des tests +> de régression supplémentaires (Lot 2bis/9 : sérialisation à chaleur nulle, pattern à slots vides +> qui survit à la sauvegarde et à la synchro réseau) ont depuis été ajoutés, ramenant le total à +> **31** au 14 août 2026 — un chiffre différent de celui d'origine mais pour une raison saine +> (couverture élargie), pas une régression. + +**Adaptations du portage :** +- `loadPattern` écrit un `ReactorBluePrintData` typé (57 `PatternData`) au lieu du tag NBT `pattern`. +- Capabilities via `level.getCapability(Capabilities.FluidHandler.BLOCK, pos, null)`. +- `ForgeRegistries.FLUIDS` → `BuiltInRegistries.FLUID`, annotations `net.neoforged.neoforge.gametest`. +- La structure va dans `data/createnuclear/structure/` (**singulier** en 1.21, `structures` en 1.20.1). + +**Bug NeoForge corrigé au passage** (absent de Forge) : `ReactorInputFluidManager` lisait +`getFluidInTank(handler.getTanks())` — un index hors bornes — dans `getInventory()` **et** +`extractFluids()`. Corrigé en `getFluidInTank(0)`. Un `LOGGER.warn` de debug oublié dans +`getBlocksPosition()`, qui spammait à chaque appel, a aussi été retiré. + +--- + +## 8. Hors périmètre de ce rapport + +Le reste du mod présente aussi des écarts. Inventaire complet en §9. + +--- + +## 9. Ce qui n'est PAS porté de Forge vers NeoForge + +> 📄 **Cette section est reprise et approfondie dans [`PARITE_FORGE_NEOFORGE.md`](PARITE_FORGE_NEOFORGE.md)**, +> qui détaille pour chaque feature manquante ses points d'accroche, sa difficulté et l'ordre de +> travail conseillé. Le présent document reste centré sur le réacteur. + +État au 6 août 2026, branche `V2-Reacteur`. Le comptage brut donne **42 fichiers Forge sans +équivalent NeoForge**, mais 6 sont en réalité présents sous un autre nom — le vrai reste est +**36 fichiers**, plus des écarts internes sur des fichiers partagés. + +### 9.1 Faux positifs — présents mais renommés ou déplacés + +Ne pas les reporter comme manquants lors d'une synchro : + +| Forge | NeoForge | +|---|---| +| `content/multiblock/rod/CNRodTypes` | `content/rod/CNRodTypes` | +| `foundation/damageTypes/CNDamageSources` | `foundation/damages**T**ypes/CNDamageSources` | +| `content/equipment/armor/ArmorMaterials` | `CNArmorMaterials` | +| `infrastructure/config/CExplode` | `CExplose` *(faute de frappe côté Neo)* | +| `input/fluid/PlayerInteract**R**eactorFluidInput` | `PlayerInteract**e**ReactorFluidInput` *(faute de frappe)* | +| `irradiated/cat/CatLieOnBedGoal`, `CatSitOnBlockGoal` | `IrradiatedCatLieOnBedGoal`, `IrradiatedCatSitOnBlockGoal` | + +### 9.2 Features entièrement absentes + +**① Jauges DisplayLink du réacteur — 9 fichiers** ← *le manque le plus visible en jeu* + +`CNDisplaySources` · `AbstractReactorStatDisplaySource` · `HeatDisplaySource` · +`FuelDisplaySource` · `CoolerDisplaySource` · `LiquidLevelDisplaySource` · +`ReactorSizeDisplaySource` · `ReactorDisplayConstants` · `ReactorGaugeRenderer` + +NeoForge n'a que `ReactorSummary` + `ReactorSummaryDisplaySource`. Côté Forge, `CNBlocks` +attache en plus au contrôleur `.transform(displaySource(CNDisplaySources.HEAT))`, +`LIQUID_LEVEL`, etc. — **impossible de brancher un Display Link sur une statistique précise +du réacteur** côté NeoForge. Le code réacteur nécessaire (`ReactorDisplayState`, +`getMultiblockSize`, `getInputFluidManager`) est désormais en place, donc c'est un portage +direct sans prérequis. +*NeoForge a en plus `ReactorGaugeOverrides`, qui n'existe pas côté Forge.* + +**② Poudre de neige (Snow Powder) — 4 fichiers** + +`SnowPowderRecipe` · `SnowPowderRecipeGen` · `CNSnowPowderRecipeGen` · `FanSnowPowderCategory` (JEI) + +Recette de ventilateur complète, avec sa catégorie JEI. Rien de tout ça côté NeoForge. + +**③ Vache irradiée + abstraction des animaux — 5 fichiers** + +`IrradiatedCow` · `IrradiatedCowModel` · `IrradiatedCowRenderer` · `IrradiatedAnimal` · `AnimalUtil` + +NeoForge a le chat, le loup et le poulet, mais **pas la vache**. Il lui manque aussi la classe +de base `IrradiatedAnimal` et l'utilitaire `AnimalUtil` : ses animaux dupliquent donc la +logique que Forge a factorisée. C'est le dossier le plus divergent hors réacteur +(`IrradiatedCat` 384 lignes d'écart, `IrradiatedWolf` 333). + +**④ Worldgen piloté par config — 2 fichiers** + +`CNPlacementModifiers` · `ConfigPlacementFilter` + +Filtre de placement lisant la config : sans lui, les options de génération de minerai +(`CWorldGen`) ne sont probablement pas respectées. + +**⑤ Datagen de recettes — 2 fichiers** + +`CNDeployingRecipeGen` · `CNProcessingRecipeGen` — des recettes existent donc côté Forge +et pas côté NeoForge. + +**⑥ Radiation — 2 fichiers** + +`IRadiationCapability` · `RadiationProvider` + +Attendu : NeoForge 1.21 remplace les capabilities Forge par les *data attachments*. +`RadiationCapability` existe et diverge de 186 lignes. **À vérifier fonctionnellement** +plutôt qu'à porter à l'identique. + +**⑦ Compat externe — 2 fichiers** + +`Mods` · `AlexscaveCompat` — intégration Alex's Caves absente. + +**⑧ Mixins client — 2 fichiers** + +`CameraAccessor` · `GameRendererMixin` — effet visuel (probablement lié au shader de radiation). +NeoForge a à la place `AntiRadiationArmorTextureMixin`, qui n'existe pas côté Forge. + +**⑨ Divers — 6 fichiers** + +`CNOpenPipeEffectHandlers` (effets des tuyaux ouverts) · `UraniumOreItem` · +`CriterionTriggerBase` (base des advancements custom) · `RodsTooltipHandler` + +`RodsStats` (tooltips détaillés des barres) · `SimplexNoise` + +**⑩ Extracteur d'irradiation de biome — 1 fichier** + +`BiomeIrradationExtractorItem`. ⚠️ **Déjà porté en amont** : les 4 commits d'`origin/V2` que +cette branche n'a pas encore intégrés l'ajoutent sous le nom `BiomeIrradiationExtractorItem`. +Il apparaîtra automatiquement au merge. + +### 9.3 Portés mais non audités + +Ces fichiers existent des deux côtés mais divergent fortement. Un gros diff n'est **pas** +une preuve de feature manquante — l'API 1.21 en explique une grande part. Aucun n'a été +audité ligne à ligne, contrairement au domaine réacteur. + +| Fichier | Lignes divergentes | +|---|---| +| `CNBlocks` | 701 | +| `CNItems` | 457 | +| `foundation/data/recipe/CNStandardRecipeGen` | 395 | +| `foundation/advancement/CNAdvancement` | 394 | +| `content/contraptions/irradiated/cat/IrradiatedCat` | 384 | +| `compat/jei/CreateNuclearJEI` | 344 | +| `content/contraptions/irradiated/wolf/IrradiatedWolf` | 333 | +| `CNCreativeModeTabs` | 249 | +| `content/radiation/capability/RadiationCapability` | 186 | + +Le lot 9 a montré que ces écarts cachent de vrais bugs : la capacité de stress et les +`addLayer` manquants étaient tous les deux dans `CNBlocks`. + +### 9.4 Bug `extractFluids` ✅ CORRIGÉ dans les deux versions + +`ReactorInputFluidManager.extractFluids` ne décrémentait jamais `fluidNeeded` entre les +handlers : le montant demandé était traité comme un quota **par entrée** au lieu d'un total. +Un réacteur demandant 10 unités avec deux entrées de 10 les vidait toutes les deux, soit 20 +retirées. Plus le joueur posait d'entrées, plus le caloporteur disparaissait vite. + +Un garde `if (toExtract > 1)` avalait aussi les demandes d'exactement 1 unité — précisément +ce que demande `FluidConsumptionRateCalculator` en bas de la courbe de consommation. + +Corrigé à l'identique dans les deux repos (implémentations byte-identical). Les deux tests +`*_expectedContract` passent, les deux tests qui figeaient le comportement bogué sont +supprimés, et le javadoc — qui promettait « true si le montant complet a été extrait » alors +que le code renvoyait true sur toute extraction partielle — documente désormais le vrai +contrat. + +**`runGameTestServer` sort maintenant en code 0 des deux côtés** (Forge 28 tests, +NeoForge 31 au 14 août 2026 — des tests de régression ont été ajoutés depuis, voir Lot 8) : +il peut servir de garde-fou CI. + +### 9.5 Ordre suggéré pour la suite + +1. ~~**Merger `origin/V2`**~~ ✅ fait — un seul conflit, l'import prévu dans `CNItems`. +2. **Jauges DisplayLink** — le plus visible, sans prérequis, le réacteur expose déjà tout. +3. ~~**Corriger `extractFluids`**~~ ✅ fait dans les deux repos. +4. **Worldgen config** — silencieux mais fausse la génération de minerai. +5. **Vache irradiée + `IrradiatedAnimal`/`AnimalUtil`** — permet aussi de dédupliquer chat/loup/poulet. +6. Snow Powder, datagen manquant, compat Alex's Caves, mixins client. +7. **Auditer `CNBlocks` et `CNItems`** en dernier, mais ne pas l'oublier : c'est là qu'étaient + cachés deux des six bugs du lot 9. \ No newline at end of file diff --git a/PROTOTYPE_EVOLUTION_MOBS_IRRADIES.md b/PROTOTYPE_EVOLUTION_MOBS_IRRADIES.md new file mode 100644 index 0000000..ae3d810 --- /dev/null +++ b/PROTOTYPE_EVOLUTION_MOBS_IRRADIES.md @@ -0,0 +1,1519 @@ +# Évolution dynamique des mobs irradiés — Prototype d'architecture + +> Document généré à partir d'une session de conception. Le code ci-dessous est un **prototype +> d'évaluation architecturale**, pas une PR : il montre jusqu'où le principe "aucune paire +> d'entités codée à l'avance" peut être tenu, avec les vraies limites rencontrées en cours de +> route. Rien de ce code n'est intégré au build (pas de fichiers `.java` créés, pas d'enregistrement +> dans `CreateNuclear.onCtor`). + +--- + +## Prompt de vérification + +À utiliser (par moi plus tard, par un autre agent, ou par un dev qui relit) pour confirmer ou +infirmer ce qui est écrit dans ce document avant toute implémentation réelle : + +``` +Contexte : CreateNuclearNeoForge, mod NeoForge pour Minecraft 1.21.1 (neo_version=21.1.247, +mappings officiels + Parchment 2024.11.17), package racine net.nuclearteam.createnuclear. + +Le document PROTOTYPE_EVOLUTION_MOBS_IRRADIES.md propose une architecture "Trait" pour un système +où un mob irradié acquiert dynamiquement des attributs/comportements/apparence des entités qu'il +tue, sans code écrit par paire d'entités. Vérifie les points suivants contre l'état réel du projet +et des sources Minecraft décompilées (via ./gradlew, cache neoformruntime sous +~/.gradle/caches/neoformruntime/intermediate_results/*_output.jar) : + +1. Les signatures d'API citées sont-elles toujours exactes dans la version actuelle du projet + (mappings/version MC ont-ils changé) ? En particulier : + - LivingEntity#getAttribute(Holder), AttributeMap#hasAttribute/getInstance + - AttributeInstance#addOrReplacePermanentModifier, le record AttributeModifier(ResourceLocation, + double, AttributeModifier.Operation) + - PartDefinition#bake(int, int), EntityModelSet#bakeLayer(ModelLayerLocation), ModelPart#getChild + - KeyframeAnimations#animate (fail-safe via Optional/getAnyDescendantWithName) + - SimpleJsonResourceReloadListener(Gson, String) + AddReloadListenerEvent + - VibrationSystem / VibrationSystem.User (Warden.java, Warden$VibrationUser) +2. Le mécanisme du "sonar" du Warden (tendrilAnimation, entity event byte 61, onReceiveVibration + dans Warden$VibrationUser) est-il toujours implémenté ainsi, ou a-t-il été refactoré ? +3. TurtleModel#createBodyLayer définit-il toujours "shell" comme un nom de cube (CubeListBuilder + .addBox("shell", ...)) à l'intérieur du part "body", plutôt que comme un PartDefinition séparé ? + Si oui, la limite "on ne peut pas extraire juste la carapace via ModelPart#getChild" tient + toujours. Si Mojang a changé le modèle, cette limite doit être réévaluée. +4. Les conventions du projet citées sont-elles toujours d'actualité : + - RadiationCapability (net.nuclearteam.createnuclear.content.radiation.capability) comme + référence de style pour un attachment Codec/StreamCodec + - CNAttachmentTypes.java comme point d'enregistrement des AttachmentType + - CreateNuclear.onCtor(...) comme point d'enregistrement séquentiel des sous-systèmes + - Absence de LivingDeathEvent existant dans le mod (donc pas de conflit avec un hook existant) + - Absence de GeckoLib (rendu 100% vanilla EntityModel/HierarchicalModel) +5. Le code des fichiers proposés compile-t-il tel quel une fois copié dans le projet (imports, + noms de packages, méthodes réellement publiques) ? Signale toute erreur de compilation probable. +6. Y a-t-il, depuis, une meilleure primitive vanilla/NeoForge pour l'un des trois tiers (attributs, + comportement, apparence) qui rendrait une partie de cette architecture obsolète ou plus simple ? + +Réponds point par point : CONFIRMÉ / INFIRMÉ / À REVÉRIFIER, avec la source (fichier + ligne) à +l'appui pour chaque point. +``` + +--- + +## Contexte du projet (vérifié dans les sources au moment de l'écriture) + +- Mod NeoForge, Minecraft **1.21.1**, `neo_version=21.1.247`, mappings officiels + Parchment + `2024.11.17` (`gradle.properties`). +- Package racine : `net.nuclearteam.createnuclear`, classe mod `CreateNuclear.java` + (`@Mod(CreateNuclear.MOD_ID)`, `MOD_ID = "createnuclear"`). +- Structure : `api/` (points d'extension publics), `content/` (fonctionnalités), `foundation/` + (utilitaires/bases), `infrastructure/` (config, worldgen, datagen). +- Trois mobs irradiés existent déjà : `IrradiatedWolf`, `IrradiatedChicken`, `IrradiatedCat` + (tous `TamableAnimal`, pas pensés à l'origine pour "chasser et évoluer"). Aucun mob + `Monster`/"Mutant" générique n'existe encore. +- `RadiationCapability` (`content/radiation/capability/RadiationCapability.java`) est le modèle de + style pour un attachment NeoForge : `Codec` via `RecordCodecBuilder`, `StreamCodec` via + `StreamCodec.composite`, enregistré dans `CNAttachmentTypes.java` + (`AttachmentType.builder(...).serialize(CODEC).sync(STREAM_CODEC)`). +- Aucun `LivingDeathEvent` n'est utilisé nulle part dans le mod — point d'insertion libre. +- Aucune dépendance GeckoLib — rendu 100% vanilla (`EntityModel`/`HierarchicalModel` + + `Renderer`/`Model` classiques, ex. `IrradiatedWolfModel.java`/`IrradiatedWolfRenderer.java`). +- Pas de `JsonDataLoader` maison existant ; le mod suit surtout le framework de recipe-gen de + Create. Le loader JSON proposé ici (`EntityTraitMapping`) suit le patron vanilla + `SimpleJsonResourceReloadListener`, pas un patron déjà présent dans le repo. + +--- + +## Résumé de la discussion + +### Question initiale + +Faire évoluer dynamiquement des mobs irradiés : un mob irradié qui tue une autre entité récupère +certaines de ses caractéristiques (capacités, comportements, attributs, apparence) **sans que +chaque interaction soit codée à l'avance**. Exemples donnés : tuer un Warden → attaque à distance + +détection sonore ; tuer une tortue → carapace adaptée à sa taille. + +### Ce qui est faisable, et à quel prix + +**Attributs (santé, dégâts, vitesse...)** — totalement générique. L'API `Attribute`/ +`AttributeInstance` permet de lire n'importe quelle entité tuée et de fusionner ses valeurs sur le +mob irradié sans code par paire. + +**Comportements/capacités** — semi-générique. Les `Goal`/`Brain` vanilla sont écrits en dur pour +une classe précise (cast interne), donc pas copiables tels quels par réflexion. Solution : un +système de **Traits** enregistrés en Java (une classe par capacité, pas par paire), activés soit +par une **table datapack JSON** `EntityType -> [traitId]`, soit par une **sonde réflexive** +(`instanceof VibrationSystem`, etc.) quand c'est fiable. + +**Apparence/texture/modèle** — le plus contraint. Les modèles vanilla (`LayerDefinition`/ +`PartDefinition`, depuis 1.17) forment un arbre de parties nommées, introspectable à l'exécution +via `EntityModelSet`. On peut extraire une sous-partie nommée et sa texture d'origine sans aucune +fusion de texture. Limite réelle découverte en lisant `TurtleModel.java` : la carapace de la +tortue n'est **pas** un `ModelPart` séparé, c'est un **nom de cube** (`addBox("shell", ...)`) à +l'intérieur du part `"body"` — ce nom n'est pas conservé après `bake()`, et `ModelPart` n'expose +aucun accès public à sa liste de cubes. Donc "récupérer juste la carapace" n'est pas possible avec +l'API publique telle quelle ; il faudrait re-modéliser cette partie soi-même en sous-part séparée. + +### Le détour Warden : sonar vs sonic boom + +Deux mécanismes séparés, vérifiés dans les sources décompilées +(`net/minecraft/world/entity/monster/warden/Warden.java`, +`net/minecraft/world/entity/ai/behavior/warden/SonicBoom.java`, +`net/minecraft/client/model/WardenModel.java`) : + +- **Sonic boom (attaque)** : une `Behavior` pilotée par `MemoryModuleType` (Brain), donc + liée au système `Brain` — pas portable telle quelle sur un mob à `goalSelector` classique sans + réimplémentation (le code source fait ~20 lignes utiles, facilement réécrit en `Goal`). La + particule part du point d'ancrage `EntityAttachment.WARDEN_CHEST` (la poitrine, pas les yeux ni + la tête). L'animation associée (`WardenAnimation.WARDEN_SONIC_BOOM`) cible surtout les parties + `"body"` et `"right_ribcage"`, pas `"head"`. +- **Sonar / écoute (ce qui intéressait l'utilisateur)** : beaucoup plus simple à généraliser. + `Warden implements VibrationSystem` (interface générique de Mojang, faite pour être implémentée + par n'importe quelle entité). `VibrationUser#onReceiveVibration` (ligne ~644 de `Warden.java`) + fait juste `level.broadcastEntityEvent(this, (byte)61)`. Côté client, + `handleEntityEvent(id==61)` met `this.tendrilAnimation = 10` — **un simple compteur entier qui + décroît**, pas une `AnimationDefinition`/keyframes. `getTendrilAnimation(partialTick)` le lisse + en 0→1, et `WardenModel.animateTendrils()` applique + `rot = tendrilAnimation × cos(ageInTicks × 2.25) × π × 0.1` sur une paire de parties symétriques. + Cette formule ne dépend d'aucune géométrie spécifique au Warden : elle est directement réutilisable + sur n'importe quelle paire de parties nommées d'un autre modèle. + +### La question "peut-on éviter de tout prévoir" — la vraie réponse + +Deux choses différentes : + +- **Extraction générique de données au moment du kill** (attributs via l'API `Attribute`, + capacités via `instanceof`/structure de `PartDefinition`) : déjà "automatique", un seul moteur + écrit une fois interprète n'importe quelle victime. +- **Génération de code à la volée** (bytecode au runtime via ASM/ByteBuddy) : techniquement + possible sur la JVM mais inutile et fragile ici — personne ne fait ça en modding Minecraft pour + cette raison (versions MC changeantes, debug quasi impossible). + +La bonne architecture : extraction générique → objet de données neutre → **un seul moteur +générique** qui l'interprète et agit (attributs, activation de capacité, greffe de partie de +modèle). Aucune classe spécifique par entité rencontrée. + +**Limite non contournable** : le JVM ne permet pas d'attacher une interface Java (ex. +`VibrationSystem`) à une instance déjà créée. Le mob irradié doit **déjà** implémenter cette +interface (câblage dormant, toujours présent, une seule fois sur sa classe) ; un `Trait` ne fait +qu'activer un booléen consulté à l'intérieur de ce câblage. C'est la seule "prévision" +incontournable, et elle porte sur le **tueur**, jamais sur la victime. + +--- + +## Architecture proposée + +``` +api/trait/ + Trait.java — interface, une implémentation par capacité (pas par paire d'entités) + IrradiatedEvolver.java — interface que le mob tueur doit implémenter pour participer + TraitRegistry.java — registry Java des Trait + sondes de réflexion (fallback) + EntityTraitMapping.java — reload listener JSON : EntityType -> liste de traits + AcquiredTraits.java — attachment NeoForge : quels traits un mob a acquis (persisté + synchro) + AttributeMerger.java — Tier 1, 100% générique, aucune donnée à fournir + +content/traits/ + TraitAcquisitionHandler.java — hook LivingDeathEvent qui orchestre tout + VibrationSensingTrait.java — Tier 2 : exemple "sonar du Warden" + appearance/ + PartGraftExtractor.java — Tier 3 : extraction générique d'une partie de modèle + ShellAppearanceTrait.java — Tier 3 : exemple "carapace de tortue" + GraftedPartRenderLayer.java + +data/createnuclear/trait_mappings/*.json — la config datapack +``` + +--- + +## Code — Tier 1 : Attributs (100% générique, zéro donnée à fournir) + +```java +package net.nuclearteam.createnuclear.api.trait; + +import net.minecraft.core.Holder; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; + +/** + * Merges a fraction of the victim's attribute values into the acquirer's. + * Nothing here is specific to any entity: it walks the global Attribute registry and only acts on + * attributes both the victim and the acquirer actually have, discovered at kill time. + */ +public class AttributeMerger { + private static final double SHARE = 0.15; // fraction of the victim's value merged in + + public static void merge(LivingEntity acquirer, LivingEntity victim) { + ResourceLocation victimTypeId = BuiltInRegistries.ENTITY_TYPE.getKey(victim.getType()); + + BuiltInRegistries.ATTRIBUTE.holders().forEach(holder -> { + if (!victim.getAttributes().hasAttribute(holder) || !acquirer.getAttributes().hasAttribute(holder)) return; + + double victimValue = victim.getAttributeValue(holder); + AttributeInstance target = acquirer.getAttribute(holder); + if (target == null || victimValue <= 0) return; + + ResourceLocation attrId = BuiltInRegistries.ATTRIBUTE.getKey(holder.value()); + // Stable id per (attribute, source species): re-killing the same species updates + // instead of stacking; killing a different species adds a separate modifier. + ResourceLocation modifierId = ResourceLocation.fromNamespaceAndPath( + "createnuclear", "trait_attr/" + attrId.getPath() + "/" + victimTypeId.getPath()); + + target.addOrReplacePermanentModifier( + new AttributeModifier(modifierId, victimValue * SHARE, AttributeModifier.Operation.ADD_VALUE)); + }); + } +} +``` + +**Pourquoi ça marche sans rien prévoir** : `BuiltInRegistries.ATTRIBUTE` liste tous les attributs +existants (vanilla + modés), `hasAttribute()`/`getAttribute()` sont des méthodes publiques de +`LivingEntity`/`AttributeMap` qui répondent correctement pour n'importe quelle entité. Aucune +classe à écrire pour "Warden" ou "Tortue" — tuer une tortue transfère sa vitesse de nage si +l'attribut existe sur les deux, tuer un Warden transfère un peu de sa vie max, etc. + +--- + +## Code — Tier 2 : Comportements/capacités (registry de Traits, datapack JSON, fallback réflexif) + +```java +package net.nuclearteam.createnuclear.api.trait; + +import net.minecraft.resources.ResourceLocation; +import java.util.Set; + +/** + * Implemented by a mob class that can acquire traits from its kills. + * The JVM cannot attach a new interface to an existing object at runtime, so every capability a + * Trait might activate (vibration sensing, a ranged attack...) has to be pre-wired - present but + * dormant - on the class itself. Traits only flip data on/off; they never add new Java behaviour. + */ +public interface IrradiatedEvolver { + Set getAcquiredTraitIds(); + + default boolean hasTrait(ResourceLocation id) { + return getAcquiredTraitIds().contains(id); + } +} +``` + +```java +package net.nuclearteam.createnuclear.api.trait; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.gameevent.vibrations.VibrationSystem; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** Code-side registry of Trait implementations - populated once at startup, not per entity pair. */ +public class TraitRegistry { + private static final Map TRAITS = new LinkedHashMap<>(); + private static final List PROBES = new ArrayList<>(); + + private TraitRegistry() {} + + public static void register(Trait trait) { + TRAITS.put(trait.id(), trait); + } + + public static void registerProbe(ReflectiveTraitProbe probe) { + PROBES.add(probe); + } + + public static Optional get(ResourceLocation id) { + return Optional.ofNullable(TRAITS.get(id)); + } + + /** datapack mapping ∪ reflective auto-detection, de-duplicated. */ + public static List resolve(LivingEntity victim) { + List result = new ArrayList<>(); + for (ResourceLocation id : EntityTraitMapping.get(victim.getType())) { + get(id).ifPresent(result::add); + } + for (ReflectiveTraitProbe probe : PROBES) { + probe.probe(victim).ifPresent(t -> { + if (!result.contains(t)) result.add(t); + }); + } + return result; + } + + public interface ReflectiveTraitProbe { + Optional probe(LivingEntity victim); + } + + /** Built-in registration, called once from the mod constructor. */ + public static void registerBuiltins() { + register(VibrationSensingTrait.INSTANCE); + register(ShellAppearanceTrait.INSTANCE); + + // No JSON needed for this one: any victim implementing VibrationSystem (Warden, or any + // future modded entity) grants the sensing trait automatically, without a datapack entry. + registerProbe(victim -> victim instanceof VibrationSystem + ? Optional.of(VibrationSensingTrait.INSTANCE) + : Optional.empty()); + } +} +``` + +```java +package net.nuclearteam.createnuclear.api.trait; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.GsonHelper; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.entity.EntityType; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.event.AddReloadListenerEvent; + +import java.util.*; + +/** + * Datapack-driven EntityType -> Trait ids, loaded from data/<namespace>/trait_mappings/*.json. + * Adding a new interaction is a JSON file, not a Java class. + */ +public class EntityTraitMapping extends SimpleJsonResourceReloadListener { + private static Map, List> MAPPING = Map.of(); + + public EntityTraitMapping() { + super(new Gson(), "trait_mappings"); + } + + public static List get(EntityType type) { + return MAPPING.getOrDefault(type, List.of()); + } + + @Override + protected void apply(Map resources, ResourceManager manager, ProfilerFiller profiler) { + Map, List> result = new HashMap<>(); + + for (JsonElement element : resources.values()) { + JsonObject obj = element.getAsJsonObject(); + ResourceLocation entityId = ResourceLocation.parse(GsonHelper.getAsString(obj, "entity")); + EntityType type = BuiltInRegistries.ENTITY_TYPE.getOptional(entityId).orElse(null); + if (type == null) continue; + + List traits = new ArrayList<>(); + obj.getAsJsonArray("traits").forEach(je -> traits.add(ResourceLocation.parse(je.getAsString()))); + result.merge(type, traits, (a, b) -> { + List merged = new ArrayList<>(a); + merged.addAll(b); + return merged; + }); + } + + MAPPING = result; + } + + public static void register(IEventBus modEventBus) { + modEventBus.addListener((AddReloadListenerEvent event) -> event.addListener(new EntityTraitMapping())); + } +} +``` + +```java +package net.nuclearteam.createnuclear.api.trait; + +import com.mojang.serialization.Codec; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; + +import java.util.HashSet; +import java.util.Set; + +/** Attachment: which trait ids a mob has acquired. Same pattern as RadiationCapability. */ +public class AcquiredTraits { + public static final Codec CODEC = ResourceLocation.CODEC.listOf() + .xmap(list -> create(new HashSet<>(list)), c -> List.copyOf(c.traitIds)); + + public static final StreamCodec STREAM_CODEC = ByteBufCodecs + .collection(HashSet::new, ResourceLocation.STREAM_CODEC) + .map(AcquiredTraits::create, c -> c.traitIds); + + private final Set traitIds; + + private AcquiredTraits(Set traitIds) { + this.traitIds = traitIds; + } + + public AcquiredTraits() { + this(new HashSet<>()); + } + + private static AcquiredTraits create(Set ids) { + return new AcquiredTraits(ids); + } + + public Set ids() { + return traitIds; + } + + public boolean add(ResourceLocation id) { + return traitIds.add(id); + } +} +``` + +L'exemple concret du sonar, exactement la formule vérifiée dans `Warden.java`/`WardenModel.java` +(compteur qui décroît + oscillation), généralisée à n'importe quelle paire de parties nommées : + +```java +package net.nuclearteam.createnuclear.content.traits; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.LivingEntity; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.trait.IrradiatedEvolver; +import net.nuclearteam.createnuclear.api.trait.Trait; + +public class VibrationSensingTrait implements Trait { + public static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath(CreateNuclear.MOD_ID, "vibration_sensing"); + public static final VibrationSensingTrait INSTANCE = new VibrationSensingTrait(); + + @Override + public ResourceLocation id() { + return ID; + } + + @Override + public void onAcquire(ServerLevel level, LivingEntity acquirer, LivingEntity victim) { + if (acquirer instanceof IrradiatedEvolver evolver) { + evolver.getAcquiredTraitIds().add(ID); + // The VibrationSystem.User implementation itself (getListenerRadius, canReceiveVibration, + // onReceiveVibration) is pre-wired once on the mob class (see notes below) and simply + // checks evolver.hasTrait(ID) before doing anything - this call only flips that flag on. + // Nothing here is Warden-specific. + } + } +} +``` + +**Rappel de la limite** : `Warden implements VibrationSystem` est une interface Java sur la +*classe*. Le mob irradié doit **déjà** implémenter `VibrationSystem` (câblage dormant, toujours +présent), et le Trait ne fait qu'activer un booléen consulté dans `canReceiveVibration()`. + +--- + +## Code — Tier 3 : Apparence (extraction générique de partie de modèle, avec ses vraies limites) + +```java +package net.nuclearteam.createnuclear.content.traits.appearance; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.ModelLayers; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; + +import java.util.Map; +import java.util.Optional; + +/** + * Extracts a named ModelPart subtree from any registered entity model and keeps the source + * entity's own texture reference alongside it - no texture stitching needed, since a ModelPart's + * cubes carry UVs relative to whichever texture the source model was baked for. + */ +public class PartGraftExtractor { + // Only vanilla entries are listed here for the prototype; a modded EntityType would register + // its ModelLayerLocation the same way Warden/Turtle do, via a small lookup table like this one - + // still data, not a new class per entity. + private static final Map, ModelLayerLocation> MODEL_LAYERS = Map.of( + EntityType.TURTLE, ModelLayers.TURTLE, + EntityType.WARDEN, ModelLayers.WARDEN + ); + + public record PartGraft(ModelPart part, ResourceLocation sourceTexture) {} + + public static Optional extract(Entity source, String... pathToPart) { + ModelLayerLocation layer = MODEL_LAYERS.get(source.getType()); + if (layer == null) return Optional.empty(); + + ModelPart root = Minecraft.getInstance().getEntityModels().bakeLayer(layer); + ModelPart current = root; + for (String name : pathToPart) { + current = current.getChild(name); + if (current == null) return Optional.empty(); // fails safe, same as vanilla's own lookup + } + + ResourceLocation texture = Minecraft.getInstance().getEntityRenderDispatcher() + .getRenderer(source).getTextureLocation(source); + return Optional.of(new PartGraft(current, texture)); + } +} +``` + +```java +package net.nuclearteam.createnuclear.content.traits.appearance; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.LivingEntity; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.trait.IrradiatedEvolver; +import net.nuclearteam.createnuclear.api.trait.Trait; + +public class ShellAppearanceTrait implements Trait { + public static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath(CreateNuclear.MOD_ID, "turtle_shell"); + public static final ShellAppearanceTrait INSTANCE = new ShellAppearanceTrait(); + + @Override + public ResourceLocation id() { + return ID; + } + + @Override + public void onAcquire(ServerLevel level, LivingEntity acquirer, LivingEntity victim) { + // Server side only stores that the trait was acquired (synced via AcquiredTraits). + // The client resolves *which* geometry that means by calling PartGraftExtractor itself, + // at render time, from the trait id - see GraftedPartRenderLayer. + if (acquirer instanceof IrradiatedEvolver evolver) { + evolver.getAcquiredTraitIds().add(ID); + } + } +} +``` + +```java +package net.nuclearteam.createnuclear.content.traits.appearance; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.model.EntityModel; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.EntityType; +import net.nuclearteam.createnuclear.api.trait.IrradiatedEvolver; + +/** + * Renders whichever PartGraft the acquirer currently holds, anchored at a fixed offset. + * Proof-of-concept: the anchor is a single translation, and the grafted geometry is drawn in its + * static bind pose (no animation retargeting) - good enough for a shell, not for a limb that needs + * to swing with the walk cycle. + */ +public class GraftedPartRenderLayer> extends RenderLayer { + public GraftedPartRenderLayer(RenderLayerParent parent) { + super(parent); + } + + @Override + public void render(PoseStack poseStack, MultiBufferSource buffer, int packedLight, T entity, + float limbSwing, float limbSwingAmount, float partialTick, float ageInTicks, + float netHeadYaw, float headPitch) { + if (!(entity instanceof IrradiatedEvolver evolver) || !evolver.hasTrait(ShellAppearanceTrait.ID)) return; + + // In a full implementation this graft would be resolved once (on trait acquisition) and + // cached per-entity rather than re-extracted every frame; kept inline here for clarity. + PartGraftExtractor.extract(entity, EntityType.TURTLE.toString()) // placeholder source lookup + .ifPresent(graft -> { + poseStack.pushPose(); + poseStack.translate(0.0, -0.4, 0.3); // anchor point on the acquirer's own body - this is the one thing you predefine per acquirer, not per victim + float scale = entity.getBbWidth() / 1.2F; // crude size adaptation + poseStack.scale(scale, scale, scale); + VertexConsumer consumer = buffer.getBuffer(RenderType.entityCutoutNoCull(graft.sourceTexture())); + graft.part().render(poseStack, consumer, packedLight, net.minecraft.client.renderer.LightTexture.FULL_BRIGHT); + poseStack.popPose(); + }); + } +} +``` + +--- + +## Le hook qui relie tout + +```java +package net.nuclearteam.createnuclear.content.traits; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.LivingEntity; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.entity.living.LivingDeathEvent; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.trait.AttributeMerger; +import net.nuclearteam.createnuclear.api.trait.IrradiatedEvolver; +import net.nuclearteam.createnuclear.api.trait.Trait; +import net.nuclearteam.createnuclear.api.trait.TraitRegistry; + +@EventBusSubscriber(modid = CreateNuclear.MOD_ID) +public class TraitAcquisitionHandler { + + @SubscribeEvent + public static void onDeath(LivingDeathEvent event) { + if (!(event.getEntity().level() instanceof ServerLevel level)) return; + LivingEntity victim = event.getEntity(); + + if (!(event.getSource().getEntity() instanceof LivingEntity killer)) return; + if (!(killer instanceof IrradiatedEvolver)) return; // opt-in, no class-by-class check + + AttributeMerger.merge(killer, victim); // tier 1, always + for (Trait trait : TraitRegistry.resolve(victim)) { // tier 2/3, data + reflection driven + trait.onAcquire(level, killer, victim); + } + } +} +``` + +Datapack JSON — c'est ici, et seulement ici, qu'on "prévoit" une interaction, en donnée pure : + +```json +// data/createnuclear/trait_mappings/warden.json +{ + "entity": "minecraft:warden", + "traits": ["createnuclear:vibration_sensing"] +} +``` + +```json +// data/createnuclear/trait_mappings/turtle.json +{ + "entity": "minecraft:turtle", + "traits": ["createnuclear:turtle_shell"] +} +``` + +(Le trait `vibration_sensing` serait en fait accordé même sans ce fichier, via la sonde réflexive +`instanceof VibrationSystem` enregistrée dans `TraitRegistry.registerBuiltins()`.) + +--- + +## Ce que ce prototype prouve, et ce qu'il ne résout pas + +**Ça marche, générique, sans code par paire :** +- Tier 1 (attributs) : totalement automatique, zéro configuration. +- Tier 2 (comportement/capacité) : une seule classe de Trait par capacité, activable sur n'importe + quelle victime via JSON *ou* réflexion, sans jamais écrire "si Warden alors...". +- Tier 3 (apparence) : `PartDefinition.bake()` / `EntityModelSet.bakeLayer()` + `ModelPart.getChild()` + sont de vraies API publiques qui permettent d'extraire une sous-partie nommée de n'importe quel + modèle enregistré, texture d'origine comprise, sans rien recompiler. + +**Ce qui reste une limite réelle, pas un détail :** +- `IrradiatedEvolver`/`VibrationSystem` doivent être câblés une fois sur la classe du mob tueur — + le JVM ne permet pas d'attacher une interface à une instance existante. C'est la seule + "prévision" incontournable, et elle est côté tueur, pas côté victime. +- La granularité générique s'arrête au `ModelPart` nommé. En creusant `TurtleModel.java`, la + carapace n'est pas un `ModelPart` séparé mais un `addBox("shell", ...)` *nommé* à l'intérieur du + part `"body"` — ce nom n'est pas conservé après `bake()` (`ModelPart` n'expose aucun accès public + à ses cubes). Donc récupérer *juste* la carapace de la tortue par cette méthode n'est pas + possible tel quel ; il faudrait soit prendre le `"body"` entier (carapace + ventre), soit + redécouper le modèle vanilla toi-même en sous-parties dans un modèle custom que tu contrôles. +- `MODEL_LAYERS` (EntityType → ModelLayerLocation) et l'ancrage de greffe restent une table à + maintenir — petite, mais réelle : il n'existe pas d'API vanilla qui fasse cette résolution + automatiquement pour toi. + +--- + +## Addendum — le tier 2 "flag" ne suffit pas : synthèse générative par observation + +> Ajouté lors d'une session de suite. Objection soulevée par l'utilisateur, légitime : le tier 2 +> ci-dessus reste un système où **le développeur écrit l'interaction** (`VibrationSensingTrait` +> sait exactement quoi faire) et le mob se contente de cocher un flag qu'un code déjà présent +> consulte. Ce n'est pas "le mob écrit une nouvelle interaction pour un scénario X" — c'est un +> menu de déblocage. Cette section explore comment déplacer réellement le point de généricité. + +### La distinction qui compte : effecteurs (finis, pré-écrits) vs composition (générée) + +Deux couches à ne pas confondre, sous peine de se mentir sur ce qui est "généré" : + +- **Effecteurs** — bouger vers un point, infliger des dégâts de zone, jouer une particule/son, + appliquer un `MobEffect`. Doivent être pré-écrits en Java, une fois, génériques, en nombre fini. + Aucune architecture sur la JVM ne contourne ça sans génération de bytecode à la volée (ASM/ + ByteBuddy), déjà écartée plus haut pour cause de fragilité/indébogabilité. +- **Composition** — quand déclencher quel effecteur, dans quel ordre, sous quelle condition, avec + quels paramètres. C'est cette couche, et seulement elle, qui peut être 100% générée au moment du + kill, sans qu'aucune ligne n'ait été écrite pour la paire (killer, victime) précise. + +Le tier 2 initial code les deux couches en dur dans la même classe (`Trait.onAcquire`). L'addendum +sépare : un **alphabet de primitives génériques** (écrit une fois) + un **synthétiseur** qui +observe une victime et assemble un graphe *que personne n'a écrit pour ce cas* + un **interpréteur +unique** qui exécute n'importe quel graphe fait de ces primitives. + +### Alphabet générique (écrit une fois, jamais par monstre) + +```java +package net.nuclearteam.createnuclear.api.behavior; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.LivingEntity; +import java.util.List; + +public sealed interface BehaviorNode permits Sensor, Condition, Action, Sequence, Selector {} + +public non-sealed interface Sensor extends BehaviorNode { + // ex: distance à la cible, dernier event de vibration reçu, ligne de vue... + double sample(LivingEntity self, LivingEntity target); +} + +public non-sealed interface Condition extends BehaviorNode { + boolean test(double sampled); +} + +public non-sealed interface Action extends BehaviorNode { + void run(ServerLevel level, LivingEntity self, LivingEntity target); +} + +public record Sequence(List steps) implements BehaviorNode {} +public record Selector(List options) implements BehaviorNode {} // premier qui matche +``` + +Un interpréteur unique (`BehaviorInterpreter`, non détaillé ici) parcourt ce graphe à chaque tick +ou sur événement — même mécanique que le tier 2 initial, sauf que rien n'y est encore lié à un +monstre précis : c'est une machine à graphes, pas un catalogue de capacités. + +### Ce qui bascule réellement : la construction du graphe au moment du kill + +```java +package net.nuclearteam.createnuclear.api.behavior; + +import net.minecraft.world.entity.LivingEntity; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Aucune connaissance de "Warden" ou "Blaze" ici — uniquement des motifs structurels génériques + * déduits d'un historique de combat (CombatLog, à concevoir), pas d'une classe d'entité. + */ +public final class BehaviorSynthesizer { + + public static Optional synthesize(LivingEntity victim, CombatLog log) { + List observed = new ArrayList<>(); + + // 1) Motif structurel : portée de hit anormalement grande par rapport à la hitbox de la + // victime -> pas déclaré "attaque à distance", déduit de la donnée. + double reach = log.maxHitDistanceFrom(victim); + if (reach > victim.getBbWidth() * 3) { + observed.add(new Sequence(List.of( + new DistanceSensor(), + new ThresholdCondition(reach * 0.8), + new ProjectileTowardTargetAction(log.dominantDamageType(victim)) + ))); + } + + // 2) Motif comportemental : la victime a engagé le killer sans ligne de vue directe -> + // déduit de l'observation pure, marche même sans VibrationSystem/interface Mojang. + if (log.engagedWithoutLineOfSight(victim)) { + observed.add(new Sequence(List.of( + new VibrationSensor(), + new AlwaysTrueCondition(), + new AlertAndPursueAction() + ))); + } + + if (observed.isEmpty()) return Optional.empty(); + return Optional.of(observed.size() == 1 ? observed.get(0) : new Selector(observed)); + } +} +``` + +Point central : `synthesize()` ne référence aucun `EntityType` précis. Appliquée sans modification +à n'importe quelle entité future (vanilla ou moddée) présentant un pattern de combat similaire, +elle produit un graphe différent — c'est ça, "le mob écrit une interaction pour le scénario X" sans +que X ait été prévu à l'avance, au sens strict où aucune paire (killer, victime) n'est nommée dans +le code. + +`CombatLog` (fenêtre glissante d'événements de combat : dégâts reçus/infligés, distance au moment +du hit, ligne de vue, type de dégât, timestamp) est la pièce manquante qui détermine ce que le +système peut réellement "apprendre" — alimentée par `LivingHurtEvent`, pas seulement +`LivingDeathEvent`. **Non conçue dans ce document, prochaine étape.** + +### La combinaison devient de l'algèbre sur les graphes, pas un OR de flags + +```java +public static BehaviorNode combine(BehaviorNode existing, BehaviorNode newOne) { + // Fusion plate : déjà une vraie combinaison au sens où l'arbre résultant (ex: sonar-du-Warden + + // détonation-du-Creeper, priorisés) n'a été écrit par personne pour ce cas précis, seulement + // assemblé. Aller plus loin (fusionner deux Sequence qui partagent un Sensor, muter les seuils + // numériques d'une Condition selon le succès des combats suivants, crossover entre deux graphes + // acquis) est une piste type "programmation génétique légère" — déterministe et bornable + // (profondeur max, dédoublonnage, bornes numériques serveur), contrairement à un réseau de + // neurones. Non explorée plus loin ici. + return new Selector(List.of(existing, newOne)); +} +``` + +### Ce que ça change par rapport à l'architecture tier 1/2/3 ci-dessus + +- Le tier 2 initial (`Trait` + `TraitRegistry` + mapping JSON) devient un **cas particulier + dégénéré** de ce système : un `Trait` équivaut à un `BehaviorNode` pré-assemblé à la main plutôt + que synthétisé. Les sondes réflexives (`instanceof VibrationSystem`) restent valables comme *un* + générateur de `Sensor` parmi d'autres, plus rapide à écrire quand l'interface Mojang existe déjà + — mais l'observation comportementale pure (`CombatLog`) est la voie générale, qui marche même sur + des entités moddées n'implémentant aucune interface exploitable. +- "Dépendances d'un comportement" devient trivial une fois les comportements représentés en + graphe : un `Action` synthétisé référence un `Sensor` évalué avant lui dans le `Sequence`/ + `Selector` — c'est de l'ordre topologique d'un DAG, pas une dépendance ad hoc à câbler à la main. +- Le tier 1 (attributs) et le tier 3 (apparence) ne sont pas remis en cause par cet addendum — ils + restent 100% génériques par nature (API `Attribute`/`ModelPart` déjà introspectables), sans + besoin de synthèse. + +--- + +## Points ouverts pour la suite + +- **Concevoir `CombatLog`** : quelles données capturer (dégâts reçus/infligés, distance, ligne de + vue, type de dégât, timestamp), sur quelle fenêtre glissante, avec quel coût mémoire par mob + vivant — c'est la pièce qui détermine tout ce que `BehaviorSynthesizer` peut déduire. **Prochaine + étape identifiée, pas encore creusée.** +- Câbler `IrradiatedEvolver` sur un futur mob "chasseur" générique plutôt que sur les mobs + existants (Wolf/Cat/Chicken irradiés, tous `TamableAnimal`, pas pensés à l'origine pour ça). +- Décider si l'attachment `AcquiredTraits` doit vivre sur `CNAttachmentTypes.java` aux côtés de + `RadiationCapability`, ou dans un fichier dédié. +- Vérifier le comportement de `EntityTraitMapping` en multi-datapack (fusion de listes déjà gérée + via `result.merge(...)`, à tester avec de vrais conflits). +- Décider comment gérer les traits qui modifient réellement des `Goal`/`targetSelector` (pas + couvert dans ce prototype, qui se limite à un flag `hasTrait` consulté par du code déjà présent). +- Écrire `BehaviorInterpreter` (exécution du graphe `BehaviorNode`, à quelle fréquence : par tick, + sur événement, ou hybride) et les implémentations concrètes de `DistanceSensor`, + `VibrationSensor`, `ThresholdCondition`, `AlwaysTrueCondition`, `ProjectileTowardTargetAction`, + `AlertAndPursueAction` esquissées ci-dessus (signatures illustratives, pas encore vérifiées contre + les vraies contraintes de `ServerLevel`/threading). +- Définir les garde-fous de la synthèse (profondeur max du graphe, dédoublonnage de nœuds + redondants, bornes numériques serveur) avant d'envisager mutation/crossover entre graphes acquis. + +--- + +# Addendum 2 — Évolution temporelle par paliers de contamination + +> Ajouté lors d'une session de suite, sur une question différente de l'acquisition par kill +> (Tiers 1/2/3 et addendum ci-dessus) : faire évoluer un mob irradié **en fonction de son temps +> d'exposition**, pas de qui il a tué. Question initiale de l'utilisateur, légitime : un simple +> timer qui ajoute des attributs aléatoires à chaque tick est-il une voie viable ? Réponse courte +> posée en discussion : non — non-déterministe, pas testable, et sans levier naturel sur +> l'apparence/le comportement. Ce document décrit l'alternative retenue : un compteur de temps +> converti en **paliers discrets** (comme `RadiationCapability` le fait déjà pour les seuils +> d'effet, voir `radiationLevel1/2/3` → `amplifierLevel0/1/2` dans +> [`RadiationCapability.java`](src/main/java/net/nuclearteam/createnuclear/content/radiation/capability/RadiationCapability.java#L209-L212)). +> +> Statut identique au reste du document : **prototype d'évaluation, aucun fichier `.java` créé, +> rien enregistré dans `CreateNuclear.onCtor`**. Tout le code de cette section a été écrit en +> discussion, pas vérifié à la compilation. + +## Cahier des charges posé par l'utilisateur + +- Nombre de paliers : pas de plafond fixe fixé a priori (`Integer.MAX_VALUE` en théorie). +- Progression comportementale par palier : agressivité envers **toute** entité → puis restreinte + aux entités de **même espèce/tag** → puis **formation de meute** → puis **fusion par combat** + (absorber le niveau d'un mutant de même espèce tué). +- Changement de texture/modèle uniquement aux paliers "importants", pas à chaque niveau. +- Temps pour passer de niveau 1→2 : 10 min. De 2→3 : 30 min. Au-delà, niveau `n` = `e^n` minutes. +- Objection soulevée pendant la discussion, tranchée par l'utilisateur : `e^n` minutes littéral + rend le niveau ~15 (≈7 ans d'exposition continue) déjà quasi inatteignable et le niveau ~30 + dépasse l'âge de l'univers. **Décision retenue : exponentielle jusqu'à un niveau plafond, puis + croissance linéaire au-delà**, pour que la progression reste atteignable sur le très long terme + sans jamais heurter un mur numérique. + +## Modèle à deux axes : niveau continu vs phase discrète + +Point de conception central, pour ne pas répéter l'erreur "un timer qui ajoute des trucs au +hasard" sous une autre forme : **le niveau (entier non borné) et la phase de comportement (une +poignée de valeurs finies) sont deux choses séparées.** Le niveau est un curseur continu qui monte +tout seul avec le temps ; la phase est une petite table de seuils écrite une fois, qui lit ce +curseur. C'est exactement le même principe que `radiationLevel1/2/3 → amplifierLevel0/1/2` déjà +dans le mod — pas une nouveauté architecturale, juste appliqué à un axe temporel au lieu d'un axe +d'intensité. + +Autre principe repris du reste du repo (cohérent avec le refacto récent +`d2a92a4 refactor(blueprint): drop stored graphite/uranium timers and derive patternAll on +demand`) : **seuls `level` et `ticksInLevel` sont persistés/synchronisés. Phase et apparence sont +des fonctions pures de `level`, recalculées à la demande, jamais stockées séparément** — pas de +risque de désynchronisation entre "niveau" et "apparence affichée". + +## Courbe de temps par niveau — exponentielle bornée puis linéaire + +```java +package net.nuclearteam.createnuclear.api.mutation; + +/** + * Ticks nécessaires pour passer du niveau n à n+1. Exponentielle (e^n minutes) jusqu'à LEVEL_CAP, + * puis linéaire au-delà - continue à la jonction (chaque niveau après le plafond coûte exactement + * ce qu'a coûté l'atteinte du plafond), pour que les niveaux élevés restent théoriquement + * atteignables au lieu de heurter un plafond numérique (au-delà de e^~709 un double devient + * infini, et 1200 ticks/min × e^32 dépasse déjà Long.MAX_VALUE ticks). + */ +public final class LevelCurve { + private static final int LEVEL_CAP = 10; + private static final double TICKS_PER_MINUTE = 1200.0; + private static final double LEVEL_1_MINUTES = 10.0; + private static final double LEVEL_2_MINUTES = 30.0; + private static final double CAP_MINUTES = Math.exp(LEVEL_CAP); // ~22026 min (~15,3 jours) + + private LevelCurve() {} + + /** Ticks à passer au niveau n avant de basculer au niveau n+1. */ + public static long ticksToNextLevel(int level) { + double minutes; + if (level <= 1) minutes = LEVEL_1_MINUTES; + else if (level == 2) minutes = LEVEL_2_MINUTES; + else if (level < LEVEL_CAP) minutes = Math.exp(level); + else minutes = CAP_MINUTES + (double) (level - LEVEL_CAP) * CAP_MINUTES; // linéaire, pente = CAP_MINUTES/niveau + + return (long) Math.min(minutes * TICKS_PER_MINUTE, Long.MAX_VALUE / 2); + } +} +``` + +À `level == LEVEL_CAP` (10), la branche linéaire donne `CAP_MINUTES + 0`, identique à ce qu'aurait +donné l'exponentielle — la jonction est continue, pas de saut brutal au palier 10. Au-delà, chaque +niveau coûte un palier fixe de ~15,3 jours en plus : atteignable sur plusieurs mois/années de jeu +persistant, jamais un mur. + +## Attachment persisté (même patron que `RadiationCapability`) + +```java +package net.nuclearteam.createnuclear.content.mutation.capability; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; + +/** Persisté : niveau + temps passé au niveau courant. Phase et apparence sont dérivées à la + * demande (voir MutationPhase/VisualStage), jamais stockées. */ +public class MutationCapability { + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + Codec.INT.optionalFieldOf("level", 0).forGetter(MutationCapability::getLevel), + Codec.LONG.optionalFieldOf("ticksInLevel", 0L).forGetter(MutationCapability::getTicksInLevel) + ).apply(i, MutationCapability::create)); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.VAR_INT, MutationCapability::getLevel, + ByteBufCodecs.VAR_LONG, MutationCapability::getTicksInLevel, + MutationCapability::create + ); + + private int level; + private long ticksInLevel; + + public int getLevel() { return level; } + public void setLevel(int level) { this.level = level; } + + public long getTicksInLevel() { return ticksInLevel; } + public void setTicksInLevel(long ticks) { this.ticksInLevel = ticks; } + + private static MutationCapability create(int level, long ticksInLevel) { + MutationCapability cap = new MutationCapability(); + cap.setLevel(level); + cap.setTicksInLevel(ticksInLevel); + return cap; + } +} +``` + +À enregistrer dans `CNAttachmentTypes.java` à côté de `RADIATION`, même style : +`AttachmentType.builder(MutationCapability::new).serialize(CODEC).sync(STREAM_CODEC)`. + +## Phases — petite table finie, pas un palier par niveau + +```java +package net.nuclearteam.createnuclear.api.mutation; + +public enum MutationPhase { + SOLO_AGGRESSIVE(1), // cible toute entité vivante à portée + SPECIES_AGGRESSIVE(2), // se restreint aux entités de même espèce/tag + PACK_FORMING(4), // rejoint/forme une meute de mutants en phase PACK_FORMING+ + COMBAT_FUSION(8); // absorbe le niveau des mutants de même espèce tués + + public final int minLevel; + MutationPhase(int minLevel) { this.minLevel = minLevel; } + + public static MutationPhase forLevel(int level) { + MutationPhase result = SOLO_AGGRESSIVE; + for (MutationPhase phase : values()) { + if (level >= phase.minLevel) result = phase; + } + return result; + } +} +``` + +Les seuils (`1, 2, 4, 8`) sont un point de configuration à trancher plus tard (constantes, config +serveur, ou JSON comme `EntityTraitMapping` — un seul fichier de config, pas un système par +palier). Rien n'empêche `PACK_FORMING`/`COMBAT_FUSION` de rester actifs à tous les niveaux +au-dessus de leur seuil (pas de fenêtre fermante) : un mutant de très haut niveau garde toutes les +capacités des phases précédentes. + +## Le hook de tick — accumulation, passage de niveau, dispatch + +```java +package net.nuclearteam.createnuclear.content.mutation; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Level; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.tick.EntityTickEvent; +import net.nuclearteam.createnuclear.CNAttachmentTypes; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.mutation.LevelCurve; +import net.nuclearteam.createnuclear.api.mutation.MutatingHost; +import net.nuclearteam.createnuclear.api.mutation.MutationPhase; +import net.nuclearteam.createnuclear.content.mutation.capability.MutationCapability; +import net.nuclearteam.createnuclear.content.radiation.capability.RadiationCapability; + +@EventBusSubscriber(modid = CreateNuclear.MOD_ID) +public class MutationHandler { + + @SubscribeEvent + public static void onEntityTick(EntityTickEvent.Pre event) { + if (event.getEntity() instanceof LivingEntity living && living instanceof MutatingHost host) { + tick(living, host); + } + } + + private static void tick(LivingEntity entity, MutatingHost host) { + Level level = entity.level(); + if (level.isClientSide) return; + if (!RadiationCapability.canBeIrradiated(entity)) return; + + RadiationCapability radiation = entity.getData(CNAttachmentTypes.RADIATION); + boolean contaminated = radiation.getRadiation() > 0 || radiation.getContagionTicks() > 0; + if (!contaminated) return; // pas d'exposition active = pas de progression, pas de régression non plus + + MutationCapability mutation = entity.getData(CNAttachmentTypes.MUTATION); + long threshold = LevelCurve.ticksToNextLevel(mutation.getLevel()); + long ticks = mutation.getTicksInLevel() + 1; + + if (ticks >= threshold) { + int previousLevel = mutation.getLevel(); + mutation.setLevel(previousLevel + 1); + mutation.setTicksInLevel(0); + onLevelUp(entity, host, previousLevel, mutation.getLevel()); + } else { + mutation.setTicksInLevel(ticks); + } + } + + private static void onLevelUp(LivingEntity entity, MutatingHost host, int previousLevel, int newLevel) { + AttributeScaling.apply(entity, newLevel); // toujours : id de modifier stable -> replace, jamais d'empilement + + MutationPhase previousPhase = MutationPhase.forLevel(previousLevel); + MutationPhase newPhase = MutationPhase.forLevel(newLevel); + if (newPhase != previousPhase) { + PhaseGoals.swap(host, newPhase); // change de comportement seulement au changement de phase, pas à chaque niveau + } + // VisualStage.forLevel(newLevel) est une fonction pure lue côté client directement depuis + // MutationCapability#getLevel() synchronisé - aucun champ "visualStage" supplémentaire à stocker/synchroniser. + } +} +``` + +`AttributeScaling.apply` : même idée que `AttributeMerger` du Tier 1 plus haut — un +`AttributeModifier` par attribut concerné, id stable (`"mutation_level/" + attributeId`), posé via +`addOrReplacePermanentModifier` avec une valeur recalculée `f(newLevel)` à chaque palier. Remplace +au lieu d'empiler : relire les mêmes 10 minutes de jeu après un crash/reload ne double jamais le +bonus. Non détaillé ici (fonction `f` à définir : linéaire, ou elle-même plafonnée comme +`LevelCurve`). + +## Limite réelle non contournable : `goalSelector`/`targetSelector` sont `protected` + +Même famille de contrainte JVM que `IrradiatedEvolver` dans l'addendum précédent, pour la même +raison : `Mob#goalSelector` et `Mob#targetSelector` (vanilla) sont des champs `protected`, +inaccessibles depuis une classe hors du package `net.minecraft.world.entity`. Un moteur générique +extérieur ne peut donc pas ajouter/retirer un `Goal` sur un mob quelconque — **le mob mutant doit +exposer lui-même ses sélecteurs**, une fois, sur sa classe : + +```java +package net.nuclearteam.createnuclear.api.mutation; + +import net.minecraft.world.entity.ai.goal.GoalSelector; + +/** À implémenter par toute classe de mob mutant, en renvoyant ses champs goalSelector/ + * targetSelector protégés existants - le seul câblage "prévu à l'avance" nécessaire, côté mob + * mutant lui-même, jamais par palier ni par espèce croisée. */ +public interface MutatingHost { + GoalSelector getMutableGoalSelector(); + GoalSelector getMutableTargetSelector(); +} +``` + +## Swap de comportement au changement de phase + +```java +package net.nuclearteam.createnuclear.api.mutation; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.goal.GoalSelector; +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.nuclearteam.createnuclear.CNTags.CNEntityTags; + +/** Un seul Goal de ciblage actif à la fois, remplacé (pas empilé) à chaque changement de phase. */ +public final class PhaseGoals { + private PhaseGoals() {} + + public static void swap(MutatingHost host, MutationPhase newPhase) { + if (!(host instanceof Mob mob)) return; + GoalSelector targetSelector = host.getMutableTargetSelector(); + + targetSelector.removeAllGoals(goal -> goal instanceof PhaseTargetGoal); + + switch (newPhase) { + case SOLO_AGGRESSIVE -> targetSelector.addGoal(1, + new PhaseTargetGoal(mob, e -> true)); // toute entité vivante + case SPECIES_AGGRESSIVE, PACK_FORMING, COMBAT_FUSION -> targetSelector.addGoal(1, + new PhaseTargetGoal(mob, e -> + !e.getType().is(CNEntityTags.IRRADIATED_IMMUNE.tag) && e.getType() == mob.getType())); + } + // PACK_FORMING/COMBAT_FUSION ajoutent en plus leurs propres Goals sans toucher au + // ciblage - voir les deux sections suivantes, non finalisées. + } + + /** Marqueur pour retrouver/retirer le Goal installé par la phase précédente. */ + private static class PhaseTargetGoal extends NearestAttackableTargetGoal { + PhaseTargetGoal(Mob mob, java.util.function.Predicate predicate) { + super(mob, LivingEntity.class, 10, true, false, (e, l) -> predicate.test(e)); + } + } +} +``` + +**Point à vérifier avant implémentation réelle** (marqué comme tel, pas confirmé) : la signature +exacte du dernier paramètre de `NearestAttackableTargetGoal` (prédicat `TargetingConditions`-based +vs `BiPredicate` vs autre) dépend des mappings/version exacts — à +recouper avec les sources décomposées comme indiqué dans le prompt de vérification tout en haut du +document, avant de copier ce code tel quel. + +## Apparence — paliers "importants", pas un par niveau + +```java +package net.nuclearteam.createnuclear.api.mutation; + +/** Fonction pure : quel "stage" visuel afficher pour un niveau donné. Paliers rapprochés au + * début (1, 2, 4, 8, correspondant aux changements de phase), puis en puissances de 2 - cohérent + * avec le fait que le temps entre niveaux explose déjà après LEVEL_CAP, donc les changements + * visuels ralentissent naturellement avec la progression. */ +public final class VisualStage { + private VisualStage() {} + + public static int forLevel(int level) { + if (level < 1) return 0; + if (level < 8) return Integer.numberOfTrailingZeros(Integer.highestOneBit(Math.max(level, 1))) + 1; + return 31 - Integer.numberOfLeadingZeros(level); // floor(log2(level)), paliers en puissances de 2 au-delà + } +} +``` + +Chaque valeur de `forLevel` pointe vers un couple `(ModelLayerLocation, ResourceLocation texture)` +pré-modélisé à la main dans une petite table statique (`Map`) — **pas +de génération procédurale de modèle**, cohérent avec la limite déjà posée dans l'addendum +précédent sur `ModelPart`/`PartDefinition`. Le renderer du mob mutant lit +`VisualStage.forLevel(mutation.getLevel())` à chaque frame à partir du `level` déjà synchronisé, +sans champ supplémentaire. + +## Formation de meute et fusion par combat — précision de l'utilisateur + +> Clarification apportée en discussion : `COMBAT_FUSION` n'est pas "tuer n'importe quel mutant de +> même espèce absorbe son niveau" (ce que le brouillon ci-dessus laissait entendre). Le vrai +> scénario : **deux meutes, chacune avec un chef de même niveau ; les deux chefs s'affrontent, et +> le vainqueur fusionne la meute du vaincu dans la sienne.** Ça couple `PACK_FORMING` et +> `COMBAT_FUSION` — la fusion n'a de sens qu'une fois la notion de meute/chef posée, donc les deux +> sont détaillées ensemble ici plutôt que traitées comme deux bullets séparés. +> +> Précision d'interprétation à confirmer avec l'utilisateur si erronée : le chef vaincu meurt dans +> l'affrontement (c'est un combat, pas une négociation), donc la meute résultante ne peut pas être +> dirigée par lui — le code ci-dessous fait toujours atterrir les membres absorbés sous le chef +> **vainqueur**, quel que soit le sens exact de "fusionne sa meute à celle du vaincu" dans la +> formulation d'origine. + +### Registre de meutes (support commun aux deux phases) + +```java +package net.nuclearteam.createnuclear.api.mutation; + +import java.util.*; + +/** + * Registre serveur en mémoire : quelles meutes existent, qui est le chef, qui sont les membres. + * Pas de persistance dans ce prototype (à porter sur SavedData si retenu - une meute qui + * disparaît au redémarrage du serveur n'est pas forcément un problème, à trancher plus tard). + */ +public final class PackCoordinator { + private static final Map PACKS_BY_ID = new HashMap<>(); + private static final Map PACK_BY_MEMBER = new HashMap<>(); // mutantId -> packId + + private PackCoordinator() {} + + public static final class Pack { + final UUID id = UUID.randomUUID(); + UUID leaderId; + final Set memberIds = new HashSet<>(); + } + + /** Un mutant qui atteint PACK_FORMING sans meute à proximité devient chef de sa propre meute + * solo - le Goal de ralliement (non détaillé ici) le fait rejoindre une meute existante si + * un autre membre de même phase est trouvé à portée avant l'appel à cette méthode. */ + public static Pack createSoloPack(UUID leaderId) { + Pack pack = new Pack(); + pack.leaderId = leaderId; + pack.memberIds.add(leaderId); + PACKS_BY_ID.put(pack.id, pack); + PACK_BY_MEMBER.put(leaderId, pack.id); + return pack; + } + + public static Optional packOf(UUID mutantId) { + return Optional.ofNullable(PACK_BY_MEMBER.get(mutantId)).map(PACKS_BY_ID::get); + } + + public static boolean isLeader(UUID mutantId) { + return packOf(mutantId).map(p -> p.leaderId.equals(mutantId)).orElse(false); + } + + /** Le pack du vainqueur absorbe tous les membres du pack du vaincu (chef vaincu inclus, mort + * mais gardé en trace) ; le pack du vaincu disparaît. */ + public static void mergeLoserIntoWinner(UUID winnerId, UUID loserId) { + Pack winnerPack = packOf(winnerId).orElseGet(() -> createSoloPack(winnerId)); + packOf(loserId).ifPresent(loserPack -> { + for (UUID memberId : loserPack.memberIds) { + winnerPack.memberIds.add(memberId); + PACK_BY_MEMBER.put(memberId, winnerPack.id); + } + PACKS_BY_ID.remove(loserPack.id); + }); + } +} +``` + +### Ciblage prioritaire chef-contre-chef, ajouté à `PhaseGoals.swap` + +Le ciblage `SPECIES_AGGRESSIVE` déjà en place couvre les membres non-chefs ; `COMBAT_FUSION` ajoute +un second `Goal`, **de priorité plus haute** (donc évalué en premier par le `GoalSelector` — plus +petit nombre = plus prioritaire, convention vanilla), actif seulement si le mutant est lui-même +chef, et qui ne cible que d'autres chefs de même espèce **et même niveau exact** : + +```java +// dans PhaseGoals, case COMBAT_FUSION du switch précédent : +case COMBAT_FUSION -> { + targetSelector.addGoal(1, new PhaseTargetGoal(mob, speciesPredicate(mob))); // hérité de SPECIES_AGGRESSIVE + if (PackCoordinator.isLeader(mob.getUUID())) { + targetSelector.addGoal(0, new PhaseTargetGoal(mob, rivalLeaderPredicate(mob))); + } +} +``` + +```java +private static java.util.function.Predicate speciesPredicate(Mob mob) { + return e -> !e.getType().is(CNTags.CNEntityTags.IRRADIATED_IMMUNE.tag) && e.getType() == mob.getType(); +} + +/** Ne cible que les chefs de meute rivaux, de même espèce, au niveau exactement identique - la + * condition "même niveau" posée par l'utilisateur, pas "n'importe quel chef ennemi". */ +private static java.util.function.Predicate rivalLeaderPredicate(Mob self) { + int selfLevel = self.getData(CNAttachmentTypes.MUTATION).getLevel(); + return e -> e.getType() == self.getType() + && e instanceof MutatingHost + && PackCoordinator.isLeader(e.getUUID()) + && e.getData(CNAttachmentTypes.MUTATION).getLevel() == selfLevel; +} +``` + +### Le hook de fusion — `LivingDeathEvent`, même point d'insertion que l'addendum précédent + +```java +package net.nuclearteam.createnuclear.content.mutation; + +import net.minecraft.world.entity.LivingEntity; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.entity.living.LivingDeathEvent; +import net.nuclearteam.createnuclear.CNAttachmentTypes; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.mutation.MutatingHost; +import net.nuclearteam.createnuclear.api.mutation.PackCoordinator; +import net.nuclearteam.createnuclear.content.mutation.capability.MutationCapability; + +@EventBusSubscriber(modid = CreateNuclear.MOD_ID) +public class PackFusionHandler { + + @SubscribeEvent + public static void onDeath(LivingDeathEvent event) { + LivingEntity victim = event.getEntity(); + if (!(event.getSource().getEntity() instanceof LivingEntity killer)) return; + if (!(victim instanceof MutatingHost) || !(killer instanceof MutatingHost)) return; + + // Fusion réservée aux duels chef contre chef - un chef qui tue un simple membre de meute + // rivale (via le Goal SPECIES_AGGRESSIVE hérité) ne déclenche aucune fusion. + if (!PackCoordinator.isLeader(victim.getUUID()) || !PackCoordinator.isLeader(killer.getUUID())) return; + + MutationCapability victimCap = victim.getData(CNAttachmentTypes.MUTATION); + MutationCapability killerCap = killer.getData(CNAttachmentTypes.MUTATION); + if (victimCap.getLevel() != killerCap.getLevel()) return; // condition posée par l'utilisateur : même niveau exact + + PackCoordinator.mergeLoserIntoWinner(killer.getUUID(), victim.getUUID()); + } +} +``` + +Le `Goal` de cohésion des membres absorbés (non détaillé ici, mentionné dans le "non conçu" +ci-dessous) n'a rien à faire de spécial au moment de la fusion : il relit `PackCoordinator.packOf` +en continu, donc un membre dont le pack a changé d'ID se met à suivre le nouveau chef dès le tick +suivant, sans événement dédié à câbler. + +## Ce qui reste à l'état d'esquisse, pas de code vérifié + +- **Ralliement/cohésion de meute** : le `Goal` de recherche du membre le plus proche de même phase + à portée (pour rejoindre une meute existante plutôt que rester en `createSoloPack`), et le `Goal` + de cohésion (`FollowPackLeaderGoal` ou équivalent, qui relit `PackCoordinator.packOf` en continu + comme noté plus haut). Pas différent dans l'esprit des meutes de loups vanilla, mais rien de + réutilisable tel quel ici (`Wolf` vanilla n'expose pas son mécanisme de meute publiquement). + **Non conçu dans ce document.** +- **Persistance de `PackCoordinator`** : le registre proposé est en mémoire pure (`HashMap` + statique) — une meute ne survit pas à un redémarrage serveur. À porter sur `SavedData` si retenu + en l'état, ou accepter la perte comme comportement voulu. **Non tranché.** +- **Cas des chefs de niveaux différents** : la condition de fusion posée par l'utilisateur exige un + niveau exactement identique. Rien n'est spécifié pour un duel entre chefs de niveaux différents + (pas de fusion, mais le combat lui-même a-t-il lieu ? Le `Goal` `rivalLeaderPredicate` ci-dessus + ne les cible simplement jamais l'un l'autre en priorité — ils peuvent toujours s'entre-tuer via le + `Goal` `SPECIES_AGGRESSIVE` hérité, sans fusion). **Comportement par défaut, pas explicitement + demandé.** +- **`AttributeScaling.apply`** : la fonction `f(level) -> valeur de modifier` par attribut n'est + pas définie ici — à choisir en cohérence avec `LevelCurve` (elle-même plafonnée) pour éviter + qu'un mutant de très haut niveau devienne un one-shot-kill par simple empilement linéaire non + borné. +- Enregistrement réel : `MutationCapability` dans `CNAttachmentTypes.java`, `MutationHandler`/ + `PhaseGoals`/`VisualStage` dans `CreateNuclear.onCtor(...)`, et **au moins un mob candidat qui + implémente `MutatingHost`** — aucun des trois mobs irradiés existants (`IrradiatedWolf/Cat/ + Chicken`, tous `TamableAnimal`) n'a été pensé pour ça à l'origine (même remarque que dans les + "points ouverts" de l'addendum précédent). + +--- + +# Addendum 3 — Justification fictionnelle du gain de comportement par kill (pas encore tranchée) + +> Note issue d'une session de suite, sur une question de cohérence narrative (pas de réalisme, +> de fiction) posée par l'utilisateur à propos de l'addendum "synthèse générative par observation" +> ci-dessus : est-ce que le mécanisme "un mob irradié tue un Warden, en récupère une capacité type +> sonar" tient debout comme histoire pour une créature *mutée par la radiation*, ou est-ce un +> emprunt technique (le `VibrationSystem` du Warden existe déjà côté vanilla) habillé après coup ? + +## Le problème identifié + +"Absorber la capacité de ce qu'on tue" est un trope de body-horror/looter générique (The Thing, +Rogue chez Marvel, les jeux où manger un ennemi donne son pouvoir) — **pas** un trope spécifique à +la fiction nucléaire. Godzilla, les goules de Fallout, les mutants de S.T.A.L.K.E.R. mutent +l'organisme **lui-même** (gigantisme, déformation, nouvelles capacités émergeant de sa propre +biologie) ; aucun de ces référents ne donne de mécanisme pour voler un trait à un tiers. Justifier +le sonar par "il a tué un Warden donc il a son sonar" est donc plausible en survol, mais plaqué : +ça raconte une histoire de vol de pouvoir qui se trouve avoir de la radiation en toile de fond, pas +une histoire de radiation. + +## Piste de recadrage (non tranchée) + +Remplacer la causalité "transfert direct depuis la victime" par "la radiation accélère le taux de +mutation, et le stress extrême d'un combat de survie contre une menace inhabituelle **déclenche** +cette mutation accélérée dans une direction qui répond à cette menace précise" : + +- La radiation est l'accélérateur d'évolution dirigée — cohérent avec le reste du corpus (c'est + déjà son rôle dans `RadiationCapability`/Addendum 2). +- Le combat contre la victime est le **signal de stress** qui oriente la mutation suivante vers une + réponse à ce type de menace précis — pas une pompe qui transfère littéralement une capacité. +- Mécaniquement, **aucun changement** : c'est toujours `LivingDeathEvent` → `CombatLog` du combat → + motif structurel détecté → `BehaviorNode` synthétisé (cf. addendum "synthèse générative" plus + haut). Un kill de Warden produit déjà, sans qu'aucune ligne ne nomme "Warden", le motif + structurel *"la victime a engagé le killer sans ligne de vue directe"* — la même signature + qu'un Warden traquant par vibration laisserait dans le `CombatLog`. Le sonar "s'hérite" donc du + vécu du combat, pas d'un `if victim instanceof Warden` explicite : fiction recadrée et contrainte + de généricité (aucune connaissance d'`EntityType` précis dans le synthétiseur) restent + compatibles sans effort supplémentaire. + +## Statut + +Idée jugée intéressante par l'utilisateur, **pas implémentée, pas définitivement adoptée** — à +retenir comme angle par défaut si/quand ce pan du prototype est repris, mais rien dans le code des +addendums précédents ne dépend de ce choix narratif précis (il ne change que le texte de flavor, +pas `BehaviorSynthesizer`/`CombatLog`). + +--- + +# Addendum 4 — Idées de modélisation : tortue irradiée, item bloqué par le souffle du réacteur + +> Liste d'idées notées lors d'une session de suite, à garder sous la main **au moment de modéliser +> la tortue irradiée dans Blockbench**, pas un système générique comme les tiers 1/2/3 plus haut. +> Spécifique à ce seul mob, déclenché par un seul event précis (explosion du réacteur), pas par +> kill ni par palier de contamination. Rien d'implémenté, rien vérifié à la compilation. + +## Le principe + +Si un item se trouve physiquement entre le point d'origine de l'explosion du réacteur et la +tortue irradiée au moment du souffle, cet item reste visible, planté/posé sur la carapace, une fois +la mutation terminée — comme si le souffle l'avait plaqué là. + +## Idées à garder pour la modélisation Blockbench + +- **Cube-locator dédié dans le modèle custom de la tortue** (`"item_anchor"` ou similaire), pas un + cube vanilla réutilisé : contourne directement la limite posée plus haut sur `TurtleModel#"shell"` + (cube non extractible car fondu dans `"body"`) puisque c'est un `PartDefinition` nommé qu'on + contrôle nous-mêmes → accessible après `bake()` via `ModelPart.getChild(...)`, et son + positionnement Blockbench se retranscrit tel quel au rendu via `ModelPart#translateAndRotate`. +- Le locator porte transform (position + rotation) réglée à l'œil dans Blockbench, pas en Java — + un seul point à recaler si le modèle de la carapace change. + +## Idées de détection (au moment du blast) + +- Segment/raycast entre le point d'origine de l'explosion et la position de la tortue ; tester les + `ItemEntity` dont la bounding box intersecte ce segment, garder le plus proche de la source du + souffle si plusieurs candidats. +- Stocker, en plus de l'`ItemStack` capturé, la **direction du souffle** (origine → tortue, + convertie en repère local à la tortue) pour pouvoir orienter certains items en fonction de cette + direction plutôt que d'une pose fixe. + +## Idées de pose par catégorie d'item (pas par item précis) + +Classification par `instanceof`/tag d'objet (`SwordItem`, `PickaxeItem`, ...), pas par item nommé — +même logique générique que le reste du document, alphabet fini de poses : + +- **Épée** : verticale, plantée comme Excalibur bloquée — rotation fixe + léger enfoncement dans la + carapace pour donner l'impression qu'elle est coincée, pas juste posée à plat. +- **Pioche** : inclinée, comme figée en plein geste de minage — rotation fixe différente de l'épée, + pas de logique de swing réelle, juste une pose statique évocatrice. +- **Bâton (et candidats similaires, ex. hache)** : orienté selon la direction du souffle capturée à + la détection, via une rotation qui aligne l'axe de l'item sur ce vecteur plutôt qu'une pose fixe. +- **Défaut (tout le reste)** : pose brute du locator Blockbench, sans rotation additionnelle. + +## Rappel : pourquoi c'est plus simple que le Tier 3 générique plus haut + +Pas besoin d'extraire une sous-partie d'un modèle vanilla ni de gérer une texture d'origine +étrangère (`PartGraftExtractor`) : l'item se rend via l'API standard `ItemRenderer#renderStatic` +(même mécanisme que les items tenus en main ou posés sur la tête d'un Piglin/Enderman vanilla), pas +via un graft de géométrie. Le seul travail manuel réel est le réglage du locator dans Blockbench et +l'écriture des 3-4 poses par catégorie — pas un problème d'API bloquant comme pour `"shell"`. + +## Non tranché / à décider plus tard + +- Le nombre exact de catégories d'items gérées au-delà de épée/pioche/bâton (armures ? blocs ?). +- Si l'item doit rester définitivement sur la carapace ou disparaître après un certain temps/dégât. +- Si ce mécanisme est propre à la tortue irradiée seule, ou pourrait être généralisé à d'autres + mobs irradiés plus tard (pas demandé pour l'instant — portée volontairement limitée à la tortue). + +## Prompt de vérification (spécifique à cet addendum) + +À utiliser (par moi plus tard, par un autre agent, ou par un dev qui relit) pour confirmer la +faisabilité réelle de ce mécanisme et lister les classes/méthodes exactes à utiliser, **avant toute +implémentation** : + +``` +Contexte : CreateNuclearNeoForge, mod NeoForge pour Minecraft 1.21.1 (neo_version=21.1.247, +mappings officiels + Parchment 2024.11.17), package racine net.nuclearteam.createnuclear. + +L'Addendum 4 de PROTOTYPE_EVOLUTION_MOBS_IRRADIES.md propose un mécanisme spécifique à la tortue +irradiée : au moment de l'explosion du réacteur, si un ItemEntity se trouve sur le segment entre +l'origine du souffle et la tortue, l'item capturé reste visible sur la carapace (posé/planté selon +sa catégorie : épée verticale façon Excalibur bloquée, pioche inclinée façon posture de minage, +bâton/hache orienté selon la direction du souffle) une fois la mutation terminée. + +Vérifie et réponds point par point, CONFIRMÉ / INFIRMÉ / À REVÉRIFIER, avec la source +(fichier + ligne, ou nom de classe/méthode exact) à l'appui pour chaque point : + +1. Faisabilité globale : ce mécanisme est-il réalisable avec des API publiques NeoForge/vanilla + côté client ET serveur, sans bytecode généré à la volée, sans dépendance externe (pas de + GeckoLib dans ce mod) ? +2. Détection au moment du blast : + - Quelle classe/méthode représente le mieux "l'explosion du réacteur" dans le mod actuel (event + custom existant ? ExplosionEvent de NeoForge ? à créer) ? + - Level#getEntitiesOfClass(ItemEntity.class, AABB) existe-t-il toujours avec cette signature ? + - Quelle est la méthode publique la plus fiable pour tester l'intersection segment/AABB + (Clip/ClipContext, AABB#clip(Vec3, Vec3), ou une méthode maison à écrire) ? +3. Modèle Blockbench / locator : + - Un cube nommé ajouté dans un modèle custom (LayerDefinition/PartDefinition écrit à la main, + pas TurtleModel vanilla) est-il bien accessible après bake() via ModelPart#getChild(String), + et ModelPart#translateAndRotate(PoseStack) est-elle toujours publique avec cette signature ? + - Existe-t-il une meilleure primitive vanilla récente pour ce cas (ex. EntityAttachment / + système d'ancrage introduit pour Warden$SONIC_BOOM cité dans le corps du document) ? +4. Rendu de l'item : + - ItemRenderer#renderStatic(...) existe-t-il toujours avec une signature proche de celle + utilisée plus haut dans ce document, accessible depuis un RenderLayer ? + - Quel ItemDisplayContext est le plus adapté (FIXED, GROUND, ou autre) pour un item statique + posé sur une entité, par opposition à un item tenu en main ? +5. Persistance/synchro : le patron AttachmentType (RecordCodecBuilder + StreamCodec.composite), + déjà utilisé pour RadiationCapability/AcquiredTraits/MutationCapability dans ce document, est-il + le bon véhicule pour synchroniser un ItemStack + une direction (2 float ou Vec3) au client, ou + existe-t-il un helper vanilla/NeoForge plus direct pour un ItemStack seul (ItemStack.CODEC vs + ItemStack.OPTIONAL_CODEC, StreamCodec correspondant) ? +6. Classification par catégorie d'item : confirmer que SwordItem, PickaxeItem, AxeItem sont + toujours les bons types (ou si la hiérarchie DiggerItem/Tiers a changé dans cette version), et + si un ItemTags existe déjà (vanilla ou Create) qui couvrirait un de ces cas plus proprement + qu'un instanceof. +7. Le code des exemples proposés dans l'Addendum 4 compile-t-il tel quel une fois copié dans le + projet (imports, noms de packages, méthodes réellement publiques) ? Signale toute erreur de + compilation probable et la correction attendue. +``` diff --git a/README.md b/README.md index b06cef0..4d9e131 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ If you want to help us with translations, we have opened a Crowdin project. Clic # Source Code ## Fabric -https://github.com/valentinlamine/CreateNuclearFabric +https://github.com/Create-Nuclear-Team/CreateNuclearFabric ## Forge -https://github.com/Giovanniricotta2002/CreateNuclearForge +https://github.com/Create-Nuclear-Team/CreateNuclearForge ## NeoForge diff --git a/build.gradle b/build.gradle index 2522f33..2de87b2 100644 --- a/build.gradle +++ b/build.gradle @@ -70,9 +70,16 @@ neoForge { logLevel = org.slf4j.event.Level.DEBUG } + client { client() - systemProperty 'neoforge.enabledGameTestNamespaces', mod_id + gameDirectory = project.file('run') + } + + client2 { + client() + gameDirectory = project.file('run/client2') + programArguments.addAll('--username', 'Dev2') } server { @@ -90,7 +97,7 @@ neoForge { data { data() programArguments.addAll( - '--mod', mod_id, + '--mod', mod_id as String, '--all', '--output', file('src/generated/resources/').absolutePath, '--existing', file('src/main/resources/').absolutePath @@ -125,18 +132,19 @@ repositories { //maven { url = "https://maven.tterrag.com" } // Registrate maven { url = "https://mvn.devos.one/snapshots" } // Registrate maven { url = "https://raw.githubusercontent.com/Fuzss/modresources/main/maven/" } // ForgeConfigAPIPort + maven { url = "https://api.modrinth.com/maven" } // JADE } dependencies { implementation "net.neoforged:neoforge:${neo_version}" // autres dépendances Minecraft - implementation "curse.maven:jade-324717:6291517" + implementation "maven.modrinth:jade:${jade_version}" //compileOnly "mezz.jei:jei-${minecraft_version}-common-api:${jei_version}" //compileOnly "mezz.jei:jei-${minecraft_version}-forge-api:${jei_version}" implementation("mezz.jei:jei-${minecraft_version}-neoforge:${jei_version}") implementation("com.simibubi.create:create-${minecraft_version}:${create_version}:slim") { transitive = false } - implementation("net.createmod.ponder:Ponder-NeoForge-${minecraft_version}:${ponder_version}") + implementation("net.createmod.ponder:ponder-neoforge:${ponder_version}+mc${minecraft_version}") compileOnly("dev.engine-room.flywheel:flywheel-neoforge-api-${minecraft_version}:${flywheel_version}") runtimeOnly("dev.engine-room.flywheel:flywheel-neoforge-${minecraft_version}:${flywheel_version}") implementation("com.tterrag.registrate:Registrate:${registrate_version}") @@ -212,4 +220,4 @@ publishing { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index 9a8984a..9c006c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx12G org.gradle.daemon=true org.gradle.parallel=true org.gradle.caching=true -org.gradle.configuration-cache=true +org.gradle.configuration-cache=false ## Environment Properties @@ -17,10 +17,10 @@ create_version_range = [6.0.8,) #registrate_version = MC1.20-1.3.3 flywheel_minecraft_version = 1.21.1 -create_version = 6.0.8-168 -ponder_version = 1.0.64 -flywheel_version = 1.0.5 -registrate_version = MC1.21-1.3.0+62 +create_version = 6.0.10-280 +ponder_version = 1.0.82 +flywheel_version = 1.0.6 +registrate_version = MC1.21-1.3.0+67 parchment_minecraft_version=1.21.1 parchment_mappings_version=2024.11.17 @@ -31,7 +31,7 @@ minecraft_version=1.21.1 # as they do not follow standard versioning conventions. minecraft_version_range=[1.21.1] # The Forge version must agree with the Minecraft version to get a valid artifact -neo_version=21.1.211 +neo_version=21.1.247 # The Forge version range can use any version of Forge as bounds or match the loader version range neo_version_range=[21,) # The loader version range can only use the major version of Forge/FML as bounds @@ -59,9 +59,9 @@ mixin_version = 0.8.5 librarian_version = 1.+ ## Compact -jei_version=19.25.0.322 +jei_version=19.43.0.390 recipe_viewer=disabled -jade_id=5672013 +jade_version=15.10.6+neoforge top_version=1.21.1-10.0.3 ## Mod Properties @@ -83,4 +83,4 @@ mod_group_id=net.nuclearteam.createnuclear mod_authors=Create Nuclear # The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. mod_description=Create nuclear is a mod that adds a whole nuclear system to the create mod. An optimized reactor produces over two millions SU. -mixin_config = 'createnuclear.forge.mixins.json' \ No newline at end of file +mixin_config = 'createnuclear.forge.mixins.json' diff --git a/run/command_history.txt b/run/command_history.txt index 037b2ab..2fef84b 100644 --- a/run/command_history.txt +++ b/run/command_history.txt @@ -1,40 +1,58 @@ -/give Dev createnuclear:anti_radiation_boots -/give Dev createnuclear:black_anti_radiation_chestplate -/give Dev createnuclear:black_anti_radiation_helmet -/give Dev createnuclear:black_anti_radiation_leggings -/effect give Dev createnuclear:radiation -/effect give Dev minecraft:night_vision infinite 255 -/setblock -357 -47 -536 createnuclear:enriching_fire -/give Dev minecraft:debug_stick -/effect give Dev minecraft:resistance infinite 255 +/ /time set day -/gamerule doDaylightCycle false -/tick sprint 1d -/tick sprint stop -/tick sprint 1d -/tick sprint stop -/tick freeze -/tick unfreeze -/tick sprint 1d -/gamerule doDaylightCycle true -/tick sprint stop -/gamemode survival -/gamerule doMobSpawning false -/gamemode creative -/gamemode survival -/gamemode creative -/gamemode survival -/gamemode creative -/gamemode survival -/gamemode creative -/gamemode survival -/gamemode creative /gamemode survival /gamemode creative /gamemode survival +/effect give Dev createnuclear:iodine /gamemode creative /gamemode survival /gamemode creative +/locate biome createnuclear:irradiated_land +/summon createnuclear:nuclear_explosion +/fillbiome +/fillbiome ~-10 ~ ~-10 ~10 ~32 ~10 createnuclear:irradiated_land /gamemode survival +/fillbiome ~-10 ~ ~-10 ~10 ~32 ~10 createnuclear:irradiated_land +/time set day +/gamemode spectator /gamemode creative +/effect give Dev createnuclear:iodine +/effect give Dev createnuclear:radiation +/time set day +/effect clear Dev +/effect give Dev createnuclear:radiation +/effect give Dev createnuclear:radiation 30000 +/effect give Dev minecraft:regeneration infinite 255 true +/effect give Dev createnuclear:radiation +/effect give Dev createnuclear:radiation infinite +/effect give Dev minecraft:saturation infinite 255 true +/effect give Dev createnuclear:radiation infinite +/effect give Dev createnuclear:radiation +/playsound createnuclear:alarm/alarm +/playsound createnuclear:alarm/alarm block Dev ~ ~ ~ 300 2 +/playsound createnuclear:alarm/reactor_alarm block Dev ~ ~ ~ 300 2 +/playsound createnuclear:biomes/wasteland block Dev ~ ~ ~ 300 2 +/data get storage +/data get entity Dev +/data get block -459 63 531 +/effect give Dev createnuclear:radiation infinite 0 true +/effect clear Dev +/effect give Dev createnuclear:radiation infinite 0 true +/effect give Dev createnuclear:radiation +/effect give Dev createnuclear:radiation infinite 0 true +/effect give Dev minecraft:regeneration infinite 255 true +/effect clear Dev createnuclear:radiation +/effect give Dev createnuclear:radiation infinite 0 true +/summon createnuclear:irradiated_cow +/effect clear +/effect give Dev minecraft:resistance infinite 255 true +/time set day +/advancement grant Dev everything +/effect clear Dev +/effect give Dev minecraft:night_vision infinite 255 true +/time set day +/enchant Dev minecraft:efficiency 5 +/enchant Dev minecraft:fortune 3 +/advancement revoke Dev +/advancement revoke Dev everything /time set day diff --git a/run/server.properties b/run/server.properties index 5a07c65..bdf2742 100644 --- a/run/server.properties +++ b/run/server.properties @@ -1,5 +1,5 @@ #Minecraft server properties -#Wed Oct 15 10:23:51 CEST 2025 +#Fri Aug 14 21:51:07 CEST 2026 accepts-transfers=false allow-flight=false allow-nether=true diff --git a/run/world/session.lock b/run/world/session.lock deleted file mode 100644 index 0d7e5f8..0000000 --- a/run/world/session.lock +++ /dev/null @@ -1 +0,0 @@ -☃ \ No newline at end of file diff --git a/src/generated/resources/.cache/09bd1f7b209874b6c29086df91c49669495dd477 b/src/generated/resources/.cache/09bd1f7b209874b6c29086df91c49669495dd477 new file mode 100644 index 0000000..f1ae5a8 --- /dev/null +++ b/src/generated/resources/.cache/09bd1f7b209874b6c29086df91c49669495dd477 @@ -0,0 +1,2 @@ +// 1.21.1 2026-08-02T08:58:02.5864081 CreateNuclear's Custom Sounds +469b4ea17371681fcb9a666c8cf8b51176a8df3b assets/createnuclear/sounds.json diff --git a/src/generated/resources/.cache/15812fa7bc190aa8f0a8644088c7ff563925e506 b/src/generated/resources/.cache/15812fa7bc190aa8f0a8644088c7ff563925e506 new file mode 100644 index 0000000..5950675 --- /dev/null +++ b/src/generated/resources/.cache/15812fa7bc190aa8f0a8644088c7ff563925e506 @@ -0,0 +1,25 @@ +// 1.21.1 2026-08-15T15:38:30.2163806 CreateNuclear's Processing Recipes +dda7e53d7d3c598bf66ec80b0b16f3c21ee18951 data/createnuclear/recipe/compacting/thorium_fluid_to_thorium_ingot.json +22d57898717d1a4dcca1b5be4e4cd6a23ac340c3 data/createnuclear/recipe/compacting/uranium_fluid_to_yellowcake.json +a11a9d69b96e4cd1b748cab33dabd6a2964ad6ac data/createnuclear/recipe/crushing/coal.json +49a7aa4b43af0c778821d656ec594f80c362fab5 data/createnuclear/recipe/crushing/crushed_raw_uranium.json +c1e0e107502e875ee5befc176335cbd1cef7e04d data/createnuclear/recipe/crushing/granite.json +2fbb42160178800bdce2bb0c4d5af85313475b26 data/createnuclear/recipe/crushing/nitrate.json +724e99e5db2392644021999b8a694a9b20d8ea0e data/createnuclear/recipe/crushing/raw_copper.json +ede5a70a121245622455815c9ebba7a22e569b55 data/createnuclear/recipe/crushing/raw_thorium.json +27ae6cb3938a98d3aa990318050ec7d0161ae71d data/createnuclear/recipe/crushing/raw_thorium_block.json +9fbd393caf0c74349e1afffe27a9b594de657e91 data/createnuclear/recipe/crushing/raw_uranium_block.json +efc52853cb5199a32131c8eccb6d42adff342365 data/createnuclear/recipe/crushing/raw_zinc.json +f972ded24a5cf2597fa14c4f604743d7e97d23e6 data/createnuclear/recipe/deploying/reactor_fluid_input_from_fluid_pipe_and_reactor_casing.json +f02f00a8c9503a8fdb2472064a279c98db670be7 data/createnuclear/recipe/deploying/reactor_output_from_shaft_and_reactor_casing.json +8401cab3f92d2465b26fe942969e6eb3afd2d551 data/createnuclear/recipe/deploying/reactor_rod_input_from_hopper_and_reactor_casing.json +371ca9bbe8682870942f1b41ec361b8a51be2f44 data/createnuclear/recipe/enriched/enriched_yellowcake.json +fdf6d4fce42373c414542289a73f0e206ff438f2 data/createnuclear/recipe/enriched/enriching_campfire.json +0c8d7d7eae585213bb7b3bb8ca4749dabafc27a3 data/createnuclear/recipe/item_application/reactor_casing_from_steel_and_brass_casing.json +c077c12bec6544815c584cd6aee851c892d43347 data/createnuclear/recipe/mixing/liquid_nitrogen.json +93bc6d7a40f2ccb89d8d5703c4b0f6c576d5caf8 data/createnuclear/recipe/mixing/steel.json +51333dd8271ee83a6096e597fe9dcf4c26a2c071 data/createnuclear/recipe/mixing/thorium_fluid.json +e52ccded5e0955ab39320129fce8f78d50f52250 data/createnuclear/recipe/mixing/uranium_fluid.json +4e362c3fb35c7a4cf946fda91958fe6b84a59e04 data/createnuclear/recipe/pressing/graphene.json +0883773497d77efae10821cad8506662f7331e09 data/createnuclear/recipe/snow_powder/cooled_nitrogen_concentrate.json +282966a4f127d86ed7a46757303d70314d44be47 data/createnuclear/recipe/splashing/crushed_raw_lead.json diff --git a/src/generated/resources/.cache/2448df8ffe5180e3e6870fcd493b0e61d5ed7ce8 b/src/generated/resources/.cache/2448df8ffe5180e3e6870fcd493b0e61d5ed7ce8 new file mode 100644 index 0000000..d26aab4 --- /dev/null +++ b/src/generated/resources/.cache/2448df8ffe5180e3e6870fcd493b0e61d5ed7ce8 @@ -0,0 +1,2 @@ +// 1.21.1 2026-08-08T17:51:45.3883913 CreateNuclear Damage Type Tags +be715fe45426c240c8e1dd1b8c5fa096f8453d88 data/minecraft/tags/damage_type/no_knockback.json diff --git a/src/generated/resources/.cache/35ba5b194a3aa18fb27424c32b9e16e01b900a51 b/src/generated/resources/.cache/35ba5b194a3aa18fb27424c32b9e16e01b900a51 new file mode 100644 index 0000000..98a0717 --- /dev/null +++ b/src/generated/resources/.cache/35ba5b194a3aa18fb27424c32b9e16e01b900a51 @@ -0,0 +1,700 @@ +// 1.21.1 2026-08-16T19:07:08.5594412 Registrate Provider for createnuclear [Registries, Data Maps, Recipes, Advancements, Loot Tables, Tags (blocks), Tags (enchantments), Tags (items), Tags (fluids), Tags (entity_types), generic_server_provider, Blockstates, Item models, Lang (en_us/en_ud), generic_client_provider] +0b2c76c9cff305eacfdfb57c4b703f94ca6dc903 assets/createnuclear/blockstates/autunite.json +5d06bc544bcbeb7443178d66955bb5101cf696da assets/createnuclear/blockstates/autunite_pillar.json +5b375444ac5057e63776f4991589c57824574b4a assets/createnuclear/blockstates/cut_autunite.json +f402fda858988cbb5e1a6a623cb15a6c76ac7f54 assets/createnuclear/blockstates/cut_autunite_bricks.json +b88d65e7a3393caeaed8d504bf6c4615767371aa assets/createnuclear/blockstates/cut_autunite_brick_slab.json +7f788334258cfb67dfbf716dbaf1b126376d1a14 assets/createnuclear/blockstates/cut_autunite_brick_stairs.json +7bfc6778893ef6552c10e17e3489e201758d3a75 assets/createnuclear/blockstates/cut_autunite_brick_wall.json +1e246d1862a801b2253595d7fac7717a0110ce79 assets/createnuclear/blockstates/cut_autunite_slab.json +56c308e675a047a3d28757377e61e5f79c6384e3 assets/createnuclear/blockstates/cut_autunite_stairs.json +98d386985f7c185f1acab25b9d606828f788769f assets/createnuclear/blockstates/cut_autunite_wall.json +5cf183e5277aea7ac5eb2bfa88737db909c6244d assets/createnuclear/blockstates/deepslate_lead_ore.json +ba89776428914de9e6a4d068ae695ddc5d7a4881 assets/createnuclear/blockstates/deepslate_nitrate_ore.json +e4edd1e8b7aecc00e45f4c154b302d3581e18ce9 assets/createnuclear/blockstates/deepslate_thorium_ore.json +a6f90dfcfc0659663335d4c80129ce41d0c8e47a assets/createnuclear/blockstates/deepslate_uranium_ore.json +e11c7fa5830b0877af69bb18e650d2b1e6f90027 assets/createnuclear/blockstates/enriched_soul_soil.json +f6b762b1e80656d932e990210b43e4bfb209e4d8 assets/createnuclear/blockstates/enriching_campfire.json +41d2222cb4f17c8c035f1937873518ad2adca3db assets/createnuclear/blockstates/enriching_fire.json +98dd6f667ccef1f8f1d332b42b146a6c0bbfb0db assets/createnuclear/blockstates/layered_autunite.json +f10bbdbab6112c58bebf2d98dc0ed3eb9370c09c assets/createnuclear/blockstates/lead_block.json +300b8a29d6a440a60320133481041671dde65448 assets/createnuclear/blockstates/lead_ore.json +c8479fd99df3917545c86ee3ea9bfe981bf762e7 assets/createnuclear/blockstates/nitrate_ore.json +539751a5a2a28445f570cb61b89b16c31e7d5ad0 assets/createnuclear/blockstates/nitrogen.json +1eed8de7f7b90d46d3e4fb6a0e7e9abf10a8a78f assets/createnuclear/blockstates/polished_cut_autunite.json +462d22ea4a021cc368721fdb841c8a9b9176c06d assets/createnuclear/blockstates/polished_cut_autunite_slab.json +76a9a39503654b94cbe01e249292ed280446bbb6 assets/createnuclear/blockstates/polished_cut_autunite_stairs.json +f628f8c7aa1e150ad2b5a3ce87dbe7f00b462e74 assets/createnuclear/blockstates/polished_cut_autunite_wall.json +8195d52278bf58414faaaec6067905635aaa29d5 assets/createnuclear/blockstates/raw_lead_block.json +5db59637c8fdd94d90bc9748c10769eb54f97224 assets/createnuclear/blockstates/raw_thorium_block.json +63aaf78c3e0c16c2f37b069c5392e3d1a93ac058 assets/createnuclear/blockstates/raw_uranium_block.json +1c9953bedf6cec725a6db7a199d826dcdfe9dfa7 assets/createnuclear/blockstates/reactor_alarm.json +0fbc9288622efc18fe39b6c8ba89e7e2281dee26 assets/createnuclear/blockstates/reactor_casing.json +0b5bd864f1e3b0c6b0ce868245da96fd8070fb21 assets/createnuclear/blockstates/reactor_controller.json +3c259041f317bb8868fb4f177c457fc12b8d28f5 assets/createnuclear/blockstates/reactor_cooler.json +3cced3f7d35371f1881b0485ee324788adcd2c74 assets/createnuclear/blockstates/reactor_core.json +0d8ab9ccc729b8e78539a2fab7b52b6be0afb24b assets/createnuclear/blockstates/reactor_fluid_input.json +ff68065029f7d47434aaf3f60e5ec3319302d2d8 assets/createnuclear/blockstates/reactor_frame.json +36ee5c127b0548502d15bc16a638a5bac40df1b6 assets/createnuclear/blockstates/reactor_output.json +daa6730e5e83972faea54e62eb1cf0fe36aaef0a assets/createnuclear/blockstates/reactor_rod_input.json +f7504d5f748fe938bf07d2eb5d0ba46bbfa0499d assets/createnuclear/blockstates/reinforced_glass.json +664db32ecb461bb1a8774d71d4d7168cfa56803c assets/createnuclear/blockstates/small_autunite_bricks.json +d4df48b7d5c38d7cf0b9347c196024e11497ca00 assets/createnuclear/blockstates/small_autunite_brick_slab.json +b9c915389ea6cf8338d20c48e908591f8baa2108 assets/createnuclear/blockstates/small_autunite_brick_stairs.json +7407bdb3685a15929a770b144d50cdc67c9c776f assets/createnuclear/blockstates/small_autunite_brick_wall.json +57c846a957e9250bc45f2f1091bf3f78b2a77344 assets/createnuclear/blockstates/steel_block.json +3134eef054a6f9f461bf774630241414614a9109 assets/createnuclear/blockstates/thorium.json +3c5ff75a6dc4ba05ac94e0f2435e88821cd848ee assets/createnuclear/blockstates/thorium_block.json +643a4d44b491a84d0d26e1a8944dffc40e83ce14 assets/createnuclear/blockstates/thorium_ore.json +de2884054a21315d8b167f64b206be331d388420 assets/createnuclear/blockstates/uranium.json +4557f548df100ae1d05e3b5711797225f6a39673 assets/createnuclear/blockstates/uranium_ore.json +b7900786a1b29d6de95d25ca64497e78d1a3f8ce assets/createnuclear/lang/en_ud.json +861c3a5ed721d894a5ea34456194c62c24c5c6fe assets/createnuclear/lang/en_us.json +a8495d2cd5e38213683becaf1c84b2852f8b06f5 assets/createnuclear/models/block/autunite_natural_0.json +29394a22ee8655dc22ea51563411505fbcfd2dab assets/createnuclear/models/block/autunite_natural_1.json +9e4f83de1ca7a9ab5363f43fc7c3f7f4ec6164d5 assets/createnuclear/models/block/autunite_natural_2.json +8241a75180c5634be558974bc09f15600261f67f assets/createnuclear/models/block/autunite_natural_3.json +2f6b85682c569527f9f538dae16526505ce5655a assets/createnuclear/models/block/autunite_pillar.json +4a04692c39cfad137877258b4443eb4bf5298423 assets/createnuclear/models/block/autunite_pillar_horizontal.json +a48d579af38beab6fc87d3b02a7ed902b25bdf16 assets/createnuclear/models/block/cut_autunite.json +4d49f9151293582741edc0d935f3130547cf5360 assets/createnuclear/models/block/cut_autunite_bricks.json +6729240e3a6cbda812d3feb8e287f743bd6b6de5 assets/createnuclear/models/block/cut_autunite_bricks_wall_post.json +244715a4f0f6a21d055b1de3307c303a5a885c1d assets/createnuclear/models/block/cut_autunite_bricks_wall_side.json +f8d6743895a633a45eb0c565cb7f79aae9172175 assets/createnuclear/models/block/cut_autunite_bricks_wall_side_tall.json +c470ac7f3b34c8da456f221d81b45292f0657e36 assets/createnuclear/models/block/cut_autunite_brick_slab.json +d4084e8b32d197db311b575a06023bb5fd5d8aba assets/createnuclear/models/block/cut_autunite_brick_slab_top.json +e4a795c7efcfa306ac6772e2b8a23a3afc52c0ec assets/createnuclear/models/block/cut_autunite_brick_stairs.json +90a9c051a0c72398a1f052542620029275e6a676 assets/createnuclear/models/block/cut_autunite_brick_stairs_inner.json +4bb891d8f069cf043de74c0cc9d16fcbcb49ee07 assets/createnuclear/models/block/cut_autunite_brick_stairs_outer.json +d9ae523c08cbbe274a598736a8a9fd510d78d484 assets/createnuclear/models/block/cut_autunite_slab.json +14043cfcb42894ebb0db2501929ba4cae9d8bd7d assets/createnuclear/models/block/cut_autunite_slab_top.json +f66edf8ef01d16ee116ac71e742bea54e98e1724 assets/createnuclear/models/block/cut_autunite_stairs.json +e1e1e4bff55028860d776d8ecb992547fa12b1b5 assets/createnuclear/models/block/cut_autunite_stairs_inner.json +6d1c45b12d9e783e63849d15aa29d507266bd1bb assets/createnuclear/models/block/cut_autunite_stairs_outer.json +05c9937ab6b920dfbbab6c78d115cc0bff6b8d22 assets/createnuclear/models/block/cut_autunite_wall_post.json +baced15580735dd63848a96763f8c7ffe61f3376 assets/createnuclear/models/block/cut_autunite_wall_side.json +cd15b5be0dca5f621266b157b424ac37dac859dd assets/createnuclear/models/block/cut_autunite_wall_side_tall.json +9a589577d80aa23ac97312bda605b5512eff5167 assets/createnuclear/models/block/deepslate_lead_ore.json +1a125ab1e392f50375ea2f4421adc8106c5ac7be assets/createnuclear/models/block/deepslate_nitrate_ore.json +6fa74ed345ab06422eca4c254f9108b4dfabfd78 assets/createnuclear/models/block/deepslate_thorium_ore.json +6793dd91b730f4c9abea29215de16cd0751d8cbd assets/createnuclear/models/block/deepslate_uranium_ore.json +e1b8fdc0555a1fdabda54f66cca868e444d1110b assets/createnuclear/models/block/enriched_soul_soil.json +8408a3894e9ca6e45e738b81f0a1932a0b2f86a5 assets/createnuclear/models/block/layered_autunite.json +fd642aefed8f59f5575c96ad1a0251e7773f3909 assets/createnuclear/models/block/lead_block.json +c9757e3fd9841ee17366b1d88563df6ea8106513 assets/createnuclear/models/block/lead_ore.json +ed7fef54fcaf191778ffdb588ed62fa72ec892b4 assets/createnuclear/models/block/nitrate_ore.json +20a57f470b6d6ce6822c61da93e09e95bad6deee assets/createnuclear/models/block/nitrogen.json +460e9ac2c0a90607b74afc5823b737a2867a35e3 assets/createnuclear/models/block/polished_cut_autunite.json +8d0e97cda9e4098e0aa8dca93445d3b52150dcfa assets/createnuclear/models/block/polished_cut_autunite_slab.json +4fa87093074c0a325ea50ab2d3c9725a90a11e1c assets/createnuclear/models/block/polished_cut_autunite_slab_double.json +6aab787de0caf399f8b76b94c64d850e5d55c757 assets/createnuclear/models/block/polished_cut_autunite_slab_top.json +0057844c28c996dceebfc28e95e0f022a26db0aa assets/createnuclear/models/block/polished_cut_autunite_stairs.json +741e53f404a88b4aa7bf6e8246bbe3cf1d6404b5 assets/createnuclear/models/block/polished_cut_autunite_stairs_inner.json +a251d75552efea796382a4124659f9d39606461b assets/createnuclear/models/block/polished_cut_autunite_stairs_outer.json +3fcae9cce1819111bdab42b8b92a1468394db3b1 assets/createnuclear/models/block/polished_cut_autunite_wall_post.json +ad989d89e7b80a30e0860fb0f1418013fe3355d2 assets/createnuclear/models/block/polished_cut_autunite_wall_side.json +b950ac6ca2df77ffe3abd02e13c38567602e5536 assets/createnuclear/models/block/polished_cut_autunite_wall_side_tall.json +cf8b4d604330762358b21b6e079aaab1eb2987f4 assets/createnuclear/models/block/raw_lead_block.json +de9b4dee9580161263fa8020d326ac5fe4e38ed4 assets/createnuclear/models/block/raw_thorium_block.json +561c9f9a4e153fc648a3c7224812c71c8ac2da5c assets/createnuclear/models/block/raw_uranium_block.json +dedbaa09b31d53c446144816edf216d4c20253df assets/createnuclear/models/block/reactor/controller/off.json +988faa4b7af770a8256ea25247e333cbc9d14eca assets/createnuclear/models/block/reactor/controller/on.json +d58fcfe99b438b77b4a2dd8d0dd9e1f35d037bae assets/createnuclear/models/block/reactor/controller/standby.json +d5acc57be1c8ccc3e61c40cf11856933d35803b3 assets/createnuclear/models/block/reactor_alarm.json +e5cd1c3875c277d3770e723672bd290cb87406b3 assets/createnuclear/models/block/reinforced_glass.json +e94d3eb865d17234b18241d89acdec2b10a1d21a assets/createnuclear/models/block/small_autunite_bricks.json +0632d6a6ba895efbfa6a347c9693240cc601e114 assets/createnuclear/models/block/small_autunite_bricks_wall_post.json +093bb2418968291015e9d3122755af3fd0b948d4 assets/createnuclear/models/block/small_autunite_bricks_wall_side.json +5a9a262da20c1b7053276c444bff017e73c923c9 assets/createnuclear/models/block/small_autunite_bricks_wall_side_tall.json +2d0c4071223fd38069cfdac403b33bd2925d6750 assets/createnuclear/models/block/small_autunite_brick_slab.json +496e7d40f96d28015e8dd1c787d4620e090ad965 assets/createnuclear/models/block/small_autunite_brick_slab_top.json +b9b18c9a633527a817ba9745a818980ff35836b5 assets/createnuclear/models/block/small_autunite_brick_stairs.json +072d33301f6734db5108d78731686fc34b32c6c3 assets/createnuclear/models/block/small_autunite_brick_stairs_inner.json +f99b30bd0cb3a8b78ed88a3a17b35b512c69ee06 assets/createnuclear/models/block/small_autunite_brick_stairs_outer.json +47f627eaccbd07bf81d1c45f95ebcc88994ad757 assets/createnuclear/models/block/steel_block.json +9333acc5ef34d03e00e0eaf24a3b48f2704a15c1 assets/createnuclear/models/block/thorium.json +9d2613725484de94788ba5075854eb225eaa4936 assets/createnuclear/models/block/thorium_block.json +e27878149b45eefa8673f2b86b6f491e2ed7a80f assets/createnuclear/models/block/thorium_ore.json +d234edb3b6bc81b7300ee65722973b66db0b82d9 assets/createnuclear/models/block/uranium.json +a4d5ee44c830e329034a46792280edea53343034 assets/createnuclear/models/block/uranium_ore.json +29394a22ee8655dc22ea51563411505fbcfd2dab assets/createnuclear/models/item/autunite.json +30b11d8da5d02a3e9cebb739b3b9efbee087573c assets/createnuclear/models/item/autunite_pillar.json +dd462819c7477f9d416f6783b27651385d3ac16f assets/createnuclear/models/item/biome_irradiation_extractor.json +55f1cb77f9e4decaa0ed9a08e71aa861c6e05366 assets/createnuclear/models/item/biome_irradiation_extractor/full.json +c9ea333225e88893332265930dc3a52dce185cf9 assets/createnuclear/models/item/biome_irradiation_extractor/half.json +0cbeee214db51866795c62777e45ca5ed980d7e7 assets/createnuclear/models/item/biome_irradiation_extractor/quarter.json +c8a996760a2e68b408df64fe3702fd8933908e35 assets/createnuclear/models/item/biome_irradiation_extractor/three_quarters.json +3036f3b383b40ca2021856366cd0f01cb279285b assets/createnuclear/models/item/black_cloth.json +3a5955f81eeed80e907bf8e2ee4df14fe42843f0 assets/createnuclear/models/item/blue_cloth.json +8cdcca32a87171e2c709e762165330b2f0389f90 assets/createnuclear/models/item/brown_cloth.json +63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/createnuclear/models/item/cat_irradiated_spawn_egg.json +63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/createnuclear/models/item/chicken_irradiated_spawn_egg.json +047d097f30f9586494547715d07271c6994acd18 assets/createnuclear/models/item/coal_dust.json +ea53b0647454c7520112d3092562edf3e692d18c assets/createnuclear/models/item/colored/black_anti_radiation_boots.json +7fe93912d45d0e46fe5a0784b89afa144a5b5c5f assets/createnuclear/models/item/colored/black_anti_radiation_chestplate.json +ff82ad2862c695467c643a36824a1a7c21cb6665 assets/createnuclear/models/item/colored/black_anti_radiation_helmet.json +a6f5fca10e3ee97be08aa6681edcd03163f003ae assets/createnuclear/models/item/colored/black_anti_radiation_leggings.json +7f182a95163f279db1f82e1461de1ea888828534 assets/createnuclear/models/item/colored/blue_anti_radiation_boots.json +093a7cdbf4c238bd3e43a235c6c785416a92b796 assets/createnuclear/models/item/colored/blue_anti_radiation_chestplate.json +8f347f56adc624ecf5395cf4b40210deecb89c18 assets/createnuclear/models/item/colored/blue_anti_radiation_helmet.json +31a7801e7544e4979274ba1af87797de7845c7eb assets/createnuclear/models/item/colored/blue_anti_radiation_leggings.json +1245464c0e927403e586779632e43d03ab2344d2 assets/createnuclear/models/item/colored/brown_anti_radiation_boots.json +2bbdcade2b01336d2551a6f3ba0fe74ac1f28fd4 assets/createnuclear/models/item/colored/brown_anti_radiation_chestplate.json +9ca5f14e548e99694c93fe85410c352dc5e44602 assets/createnuclear/models/item/colored/brown_anti_radiation_helmet.json +c95404d92cee18ce0a7a02d1b43daf588be9aa45 assets/createnuclear/models/item/colored/brown_anti_radiation_leggings.json +6f75be7a33b1d879a115c6185ecb26c61a178fa2 assets/createnuclear/models/item/colored/cyan_anti_radiation_boots.json +36c3c97c3a70dff89e81da71f14cccd858eb6edf assets/createnuclear/models/item/colored/cyan_anti_radiation_chestplate.json +62982e2d5b889f7514ed8d960f3b9e02285ede55 assets/createnuclear/models/item/colored/cyan_anti_radiation_helmet.json +81c2719c3faa1fd1d9656fab59a04fff70ee6185 assets/createnuclear/models/item/colored/cyan_anti_radiation_leggings.json +88accbbbf80de841ab8e7c48caf979becea56cd6 assets/createnuclear/models/item/colored/gray_anti_radiation_boots.json +c5fa85ecc17fb1513277b0830d67d21a1fc20c1e assets/createnuclear/models/item/colored/gray_anti_radiation_chestplate.json +2032a8422066f43e35d4a6eb9558178139d5db93 assets/createnuclear/models/item/colored/gray_anti_radiation_helmet.json +9a3698e2bab1c9abf76f3d430e48394e7c1cdeb4 assets/createnuclear/models/item/colored/gray_anti_radiation_leggings.json +bed152014d933108eec605c2b635a9dd53d3d395 assets/createnuclear/models/item/colored/green_anti_radiation_boots.json +312dbfd0ecff284db196faf29cc252dad4028f1e assets/createnuclear/models/item/colored/green_anti_radiation_chestplate.json +726a2b3d874e602f496786682a683a7519e172eb assets/createnuclear/models/item/colored/green_anti_radiation_helmet.json +e8515a775654aeba0fff47b6cb8e955311e1161a assets/createnuclear/models/item/colored/green_anti_radiation_leggings.json +8add2a19670b16578d326a28c4eeade28b0abce4 assets/createnuclear/models/item/colored/light_blue_anti_radiation_boots.json +016ea10b668f082089f2b26b84ff6aee3d893dbc assets/createnuclear/models/item/colored/light_blue_anti_radiation_chestplate.json +23d825f007338adf2ea5cefedbe7d3bee679725c assets/createnuclear/models/item/colored/light_blue_anti_radiation_helmet.json +5da56e54cef0d348d7806ac4b368f4ca2c1214e3 assets/createnuclear/models/item/colored/light_blue_anti_radiation_leggings.json +84d568b060c1aa80b43ebd1fc2482e23798f649c assets/createnuclear/models/item/colored/light_gray_anti_radiation_boots.json +dcebae7b6d5473a986500b510421f4a4b6919b61 assets/createnuclear/models/item/colored/light_gray_anti_radiation_chestplate.json +142063daeeed86791196cfed0fe571d6c84d62b1 assets/createnuclear/models/item/colored/light_gray_anti_radiation_helmet.json +9e84414a4364d4b1d1e4ae7fa9c972473d03cde1 assets/createnuclear/models/item/colored/light_gray_anti_radiation_leggings.json +1cf2fde5b06ca513c8d760fb84964fd8c4bb4a6d assets/createnuclear/models/item/colored/lime_anti_radiation_boots.json +585505cb16cc565c3628d1d20c8adb0c589c131e assets/createnuclear/models/item/colored/lime_anti_radiation_chestplate.json +1a3d0e376b7483fb35d5ff51c2cc59e57631c810 assets/createnuclear/models/item/colored/lime_anti_radiation_helmet.json +d9c2ce2b8267b1eff9ac893886371513d0479f0f assets/createnuclear/models/item/colored/lime_anti_radiation_leggings.json +58d9b6a723316df326fb28566ddc1a7b755b5f34 assets/createnuclear/models/item/colored/magenta_anti_radiation_boots.json +4af9c4c5969cd9d89b7fd1233fd6cd913b7a6e55 assets/createnuclear/models/item/colored/magenta_anti_radiation_chestplate.json +ec0b44647a4c6f602c117ccb7cc5cf3bc1b2cc40 assets/createnuclear/models/item/colored/magenta_anti_radiation_helmet.json +97ee1a3cd0dc75ff44a456324aa4eaddeb5228b4 assets/createnuclear/models/item/colored/magenta_anti_radiation_leggings.json +dfdf7d35b2b67f9956d9b7face924921fa3110f9 assets/createnuclear/models/item/colored/orange_anti_radiation_boots.json +9544b4769409c71845eab840f00eee31c380abb4 assets/createnuclear/models/item/colored/orange_anti_radiation_chestplate.json +555bf8b789f3007b6b48b8c6c8e7e6e5c456d0fc assets/createnuclear/models/item/colored/orange_anti_radiation_helmet.json +cd0aa7db8bbc9f4efd94adc6f2c6fbcd6354225c assets/createnuclear/models/item/colored/orange_anti_radiation_leggings.json +41f27edfaf12d5fa798bfd89578c029e8f88c62e assets/createnuclear/models/item/colored/pink_anti_radiation_boots.json +0b08ea95f885b74f3feaae2c508c53ab2d85481c assets/createnuclear/models/item/colored/pink_anti_radiation_chestplate.json +68e7d52fb8338ef708da419e1c6077bd23b9ebcc assets/createnuclear/models/item/colored/pink_anti_radiation_helmet.json +a3f7800a594b9c7cc36fececf9d9d782f0efae22 assets/createnuclear/models/item/colored/pink_anti_radiation_leggings.json +f322b6523f3231367dd5cbc16ed2baf6bccf5ce8 assets/createnuclear/models/item/colored/purple_anti_radiation_boots.json +1b460c2c65c0c650b2dce138a0f8a6f602073eac assets/createnuclear/models/item/colored/purple_anti_radiation_chestplate.json +7bb30708880ab503d4a26b184d68a5eb64be1292 assets/createnuclear/models/item/colored/purple_anti_radiation_helmet.json +ac5c749fba1cf69905ae4349ca6e55f454cfe0e2 assets/createnuclear/models/item/colored/purple_anti_radiation_leggings.json +b19907cdd689dd875f6fe1362dc808433e450df9 assets/createnuclear/models/item/colored/red_anti_radiation_boots.json +163d6ccd2af01076c31caf77c68d15122bb14956 assets/createnuclear/models/item/colored/red_anti_radiation_chestplate.json +8b3e87c8cbf1e2c8eb713ef73b861c44b1bcac70 assets/createnuclear/models/item/colored/red_anti_radiation_helmet.json +da10b8009824a09d8070bb4aae6082123723fe6a assets/createnuclear/models/item/colored/red_anti_radiation_leggings.json +26c9ef23e42958457c60a448757cc7f05f63b4ab assets/createnuclear/models/item/colored/white_anti_radiation_boots.json +bdccbf5384c44a96e69c6851550e97bb16a5b548 assets/createnuclear/models/item/colored/white_anti_radiation_chestplate.json +e42de2b7dc9dd60d1b3cc0d227c04cf56e9e4ef4 assets/createnuclear/models/item/colored/white_anti_radiation_helmet.json +584dd373ba67156635c705594ccde9722472826b assets/createnuclear/models/item/colored/white_anti_radiation_leggings.json +4aaf02522433eb16bff72c8d8d8ace52610fecc6 assets/createnuclear/models/item/colored/yellow_anti_radiation_boots.json +f96870ca7c71adca2072c2b4a88a65bd5af16fa6 assets/createnuclear/models/item/colored/yellow_anti_radiation_chestplate.json +841591454a46aaa9cedd45a45a5199173704dd1f assets/createnuclear/models/item/colored/yellow_anti_radiation_helmet.json +6eb902d83394cc1412a9bc4b5e6a22f17f3d1722 assets/createnuclear/models/item/colored/yellow_anti_radiation_leggings.json +4c5ade8688c0dfd0c3007c6bde5d52fb0a0f44cc assets/createnuclear/models/item/cooled_nitrogen_concentrate.json +0c682ff48601bf7f42c8561819ecede780664fbf assets/createnuclear/models/item/cut_autunite.json +11220bd60ab51e05a978a8322511c224d15bf886 assets/createnuclear/models/item/cut_autunite_bricks.json +d43ffb4c5491fcd8c98451649c3f4ceb271e8875 assets/createnuclear/models/item/cut_autunite_brick_slab.json +dfea56e99288e64e5061c621e860fa314fc31e9d assets/createnuclear/models/item/cut_autunite_brick_stairs.json +95e992c1e1c881d0f00a234a5e6906b1a5dbf149 assets/createnuclear/models/item/cut_autunite_brick_wall.json +5027aa166900571aa2e4f50ad53869b595ff3426 assets/createnuclear/models/item/cut_autunite_slab.json +bd832947d219746d3264422bc4c82f6acdc5cc3e assets/createnuclear/models/item/cut_autunite_stairs.json +4c0b115eb2a2f8d6e74c612fa6e1aa5b357e9185 assets/createnuclear/models/item/cut_autunite_wall.json +de649e8356e85e802df3e64df8fd663ce62ba16d assets/createnuclear/models/item/cyan_cloth.json +34c28d31d8b93699cc6ffab724d9c51670c0f3e2 assets/createnuclear/models/item/deepslate_lead_ore.json +e7121a329daab2859a4fbe971cea9ce1d3ab0b56 assets/createnuclear/models/item/deepslate_nitrate_ore.json +60b37c01bc3e885a25ce9b1aff4f8cb44e98f759 assets/createnuclear/models/item/deepslate_thorium_ore.json +1f160865067749c0bed163a84a61581631294141 assets/createnuclear/models/item/deepslate_uranium_ore.json +da342367b9997ac11b7165287f236ac483cc6671 assets/createnuclear/models/item/default_anti_radiation_boots.json +a1ee5609ce7559169b986d4eb17e6a5cd500d485 assets/createnuclear/models/item/default_anti_radiation_chestplate.json +42c1d356ab28f9046073d582da2cf96457366a2d assets/createnuclear/models/item/default_anti_radiation_helmet.json +809f0c1d796358d37d0e4f1df699fd13b1b9e5ed assets/createnuclear/models/item/default_anti_radiation_leggings.json +5a2694d92c4708ca23ddfa67666ea26be66b9a45 assets/createnuclear/models/item/enriched_soul_soil.json +306f5731ab788fa3cf3d75a7edfcc68b9c20613a assets/createnuclear/models/item/enriched_yellowcake.json +a3b71025626527be742999a0256e9c2290c9d42e assets/createnuclear/models/item/enriching_campfire.json +78240d0c081d144592e76af622d0c9929569db17 assets/createnuclear/models/item/graphene.json +3c0e762c21fa4fa5724f5570c190e89d247ee71b assets/createnuclear/models/item/graphite_rod.json +75bd474d73be3c041ceb82627cc438b2775e9b1b assets/createnuclear/models/item/gray_cloth.json +104ab85c7f23d9239608603e6cb2227bc60b585f assets/createnuclear/models/item/green_cloth.json +ad33dca8ecf90a8bc1ebb61c2007af72c427e9ed assets/createnuclear/models/item/layered_autunite.json +17ec52f71bd19239771c599ee80d9ffa073738af assets/createnuclear/models/item/lead_block.json +649fce08e620f39f776ab8ae8dcb17e0fd77c82f assets/createnuclear/models/item/lead_ingot.json +4d18b6f86e9ebcff28c08b9876f1819a067cd290 assets/createnuclear/models/item/lead_nugget.json +3fc1094857b79873a966d6de2dc9ec3b711caadf assets/createnuclear/models/item/lead_ore.json +f3b5417e33bf6c166d8cffbf16ab0f9893e29c6d assets/createnuclear/models/item/light_blue_cloth.json +33bd84e37cc034cdd6d6516af77f944b7399f3fa assets/createnuclear/models/item/light_gray_cloth.json +b20e1b4dd0745ead1aa2248a91df5dde465e0938 assets/createnuclear/models/item/lime_cloth.json +4799138766c26496b41807407a4b1ce2106cf7b7 assets/createnuclear/models/item/magenta_cloth.json +94fbc4170e0aebba53f00f5828089a25bf683c4c assets/createnuclear/models/item/nitrate.json +1e42471def4f88f8bb4b40755c72f5f713a19f30 assets/createnuclear/models/item/nitrate_ore.json +55e956c815f423e5a94d1f113ba7301199f272f5 assets/createnuclear/models/item/nitrogen_bucket.json +126657f82888c7b7b9e2338dfec05a7f80b1080d assets/createnuclear/models/item/nitrogen_concentrate.json +cfc8b9126dc3fe3b993c5e6201533aecc07989c3 assets/createnuclear/models/item/orange_cloth.json +9f81dccbba864441a1d76a5312216faa44e6e44b assets/createnuclear/models/item/pink_cloth.json +6d3410aa77b41ada9809f246f1d1a1a982449736 assets/createnuclear/models/item/polished_cut_autunite.json +6919e7571fa3bd76fa08b0a707f1f9367e203a49 assets/createnuclear/models/item/polished_cut_autunite_slab.json +d3459552745c002eb95585853ddec7b638b4c11f assets/createnuclear/models/item/polished_cut_autunite_stairs.json +b6c3a22d368bd0796b004ac27b8e453a16e7d14c assets/createnuclear/models/item/polished_cut_autunite_wall.json +3171211192a2b92005177fd1ee2ce7fbe2592b52 assets/createnuclear/models/item/purple_cloth.json +7da7ddaac39353657166badddc16fe9eb79f1a27 assets/createnuclear/models/item/raw_lead.json +ba58a4c086d8937d6703795a9d80435c2d450e35 assets/createnuclear/models/item/raw_lead_block.json +58c3279f0d6dfe7b88f5a85bfce6c1d683bbe2b4 assets/createnuclear/models/item/raw_thorium.json +528149130134a5b1d90552f22e1c856a2644a9dd assets/createnuclear/models/item/raw_thorium_block.json +2e30d8c1f56b02bd000509c2a6b32f4ff6c33290 assets/createnuclear/models/item/raw_uranium.json +5bad8990f31085232b63b11d295b90b581af9a82 assets/createnuclear/models/item/raw_uranium_block.json +11d78b3caf55cd1bcdeed1ad53fcfdcb7133d2f6 assets/createnuclear/models/item/reactor_alarm.json +ef76b3a3a97b5d1901d7e8ac17009381de418ab8 assets/createnuclear/models/item/reactor_blueprint_item.json +ee9b06de6d4e5f722543a83e5d9f7564ac6d7f70 assets/createnuclear/models/item/reactor_casing.json +7d0b9c3d7301e1f419441b69f152955fc69c5633 assets/createnuclear/models/item/reactor_controller.json +118e595a42c557d4eb97750ba31699a0e3f29ed8 assets/createnuclear/models/item/reactor_cooler.json +7e444d9dc776530d017fc28fe18dad0fabeedcdc assets/createnuclear/models/item/reactor_core.json +3e46c3ff9c6fc0b276549f7f63be2b4690cd3d62 assets/createnuclear/models/item/reactor_fluid_input.json +6726831326d47e5e416216e0ec1d3fd214110e89 assets/createnuclear/models/item/reactor_frame.json +69e464d730b826a0c28ed3cfeab28c4c561ec1b0 assets/createnuclear/models/item/reactor_output.json +08b156175821e1ce7820783f2f1ba92924e54a7d assets/createnuclear/models/item/reactor_rod_input.json +4db93da70d6a7549155201b7d9d68355449652ac assets/createnuclear/models/item/red_cloth.json +78a9e80073512a111cb936a516d290a824846ff2 assets/createnuclear/models/item/reinforced_glass.json +736521abdac62d6fa4292aafb8c86bb3d7c9623f assets/createnuclear/models/item/reinforced_glass_bottle.json +9b008029869830da5e8b8b2701e80a3a50945382 assets/createnuclear/models/item/small_autunite_bricks.json +9b83b53d90891eaf7aa4693eafe2876a831e0be2 assets/createnuclear/models/item/small_autunite_brick_slab.json +3e80ef1d80473c73a723d3c4b5c1409c7998d70f assets/createnuclear/models/item/small_autunite_brick_stairs.json +9286e69b3a5215a17ccb178933c2f52a9adb847f assets/createnuclear/models/item/small_autunite_brick_wall.json +7f33b090f2821bdeb07b2938b1618ad3f309248f assets/createnuclear/models/item/steel_block.json +bcb30dce2419ce1ec2e043eaff83df82ac8a4bec assets/createnuclear/models/item/steel_ingot.json +4b0492cf73c071f13538ce485419e46a164c99c7 assets/createnuclear/models/item/steel_nugget.json +d4ec5a600b482636195c7ba0c915ed5d78e8c880 assets/createnuclear/models/item/thorium_block.json +9712377d41a7153cb07638e33dd02e880609d249 assets/createnuclear/models/item/thorium_bucket.json +b636be722a513137e6ca68bdc6510c4a56a2296d assets/createnuclear/models/item/thorium_dust.json +6c63ff92f764da7ce92a99149bf2bf43c23e3727 assets/createnuclear/models/item/thorium_ingot.json +fe44d1ed2b4100ec32dda43274a085166706485d assets/createnuclear/models/item/thorium_nugget.json +954086bd19e91b833a263d3da33bb59903ce153f assets/createnuclear/models/item/thorium_ore.json +420836e3d9085a4ace8a147c25c7bd5fb28b58a1 assets/createnuclear/models/item/thorium_rod.json +2b6958059c3a4c8aee7fb4c003feba12dd0ab252 assets/createnuclear/models/item/uranium_bucket.json +7b15a9300d0f6d106e589db3dcd3294781d0bdca assets/createnuclear/models/item/uranium_ore.json +3b03793c0f5786f258c593e0b140cd6bd10c3b7b assets/createnuclear/models/item/uranium_powder.json +ea04609e8b5c12a7805b1c564bca07fefd6d38ba assets/createnuclear/models/item/uranium_rod.json +4d85657105612ca5525a14791c3e07cf6bd239b8 assets/createnuclear/models/item/white_cloth.json +63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/createnuclear/models/item/wolf_irradiated_spawn_egg.json +8bdc2fabbfc9fcc7c2ad4a3273897659d90b95ab assets/createnuclear/models/item/yellowcake.json +a1970879fd57836f5ae5d23352cdca277095bc7d assets/createnuclear/models/item/yellow_cloth.json +27b4df3c0d8de4a055a061483049f8c4790c7739 data/createnuclear/advancement/recipes/brewing/crafting/reinforced_glass_bottle.json +645c75625b389cc20363a60611842f63607dde6e data/createnuclear/advancement/recipes/building_blocks/autunite_from_stone_types_autunite_stonecutting.json +1ae444421205a2d61dadcca5cd4e2aff2997e720 data/createnuclear/advancement/recipes/building_blocks/autunite_pillar_from_stone_types_autunite_stonecutting.json +e349dda5e6ac121e22d4d93047f6da33db800b8f data/createnuclear/advancement/recipes/building_blocks/crafting/enriched_soul_soil.json +037502ba979c33bdf471f663846d446cf2c9a58d data/createnuclear/advancement/recipes/building_blocks/cut_autunite_bricks_from_stone_types_autunite_stonecutting.json +36c67a42fc9886dc7f8e3910c5da40243a0c96f1 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_slab.json +90b74a9ba34490ca3d4430a28330073bf4fdc2f6 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_slab_from_stone_types_autunite_stonecutting.json +9f93a2cdaee9acc10311d3c142e082935fa85ee6 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_slab_recycling.json +364f82f401ad323773e5645d1f20b7a6f36a028b data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_stairs.json +2d34a755bd84f74d9d87915157807b77b7d5a8e9 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_stairs_from_stone_types_autunite_stonecutting.json +746e2c38389ca0f91a1048fd1d42b65119bd930e data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_wall.json +d0078f0b6875c825181e857b16237beeccff688f data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_wall_from_stone_types_autunite_stonecutting.json +16d960287fc2033e78d6e7d7699a8fd368898b4e data/createnuclear/advancement/recipes/building_blocks/cut_autunite_from_stone_types_autunite_stonecutting.json +e4e980ce0207906bc770ebb080c01866ed68e032 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_slab.json +3681991c4b555543fb446ddfa5ab5608b3b396cf data/createnuclear/advancement/recipes/building_blocks/cut_autunite_slab_from_stone_types_autunite_stonecutting.json +caa5f9d70ae3c1fc19a453f30766c22b864e86a0 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_slab_recycling.json +fedda494df40e67506ab872ccb448ead5d2c408f data/createnuclear/advancement/recipes/building_blocks/cut_autunite_stairs.json +ce6ea9594dca48d5ac47447ffa2ed32238adc63b data/createnuclear/advancement/recipes/building_blocks/cut_autunite_stairs_from_stone_types_autunite_stonecutting.json +ffc86704c803a402b99c7524eebf221f941ea903 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_wall.json +a50c37e0fde99c662c01aece38a16f6d432b3fc3 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_wall_from_stone_types_autunite_stonecutting.json +9b542ab150da37484c151ffe3d1b6ecfeb8d0593 data/createnuclear/advancement/recipes/building_blocks/layered_autunite_from_stone_types_autunite_stonecutting.json +34b2cae240fe809ec193dae7601c6f1e381d231e data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_from_stone_types_autunite_stonecutting.json +a79a99b5a7642090b8939aed9497c97ad12e747c data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_slab.json +9091f87d4e33d96179bc40faae416784c6cb8f3a data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_slab_from_stone_types_autunite_stonecutting.json +943f287534bfe5fa90de7cbf05e739ee4899a2b1 data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_slab_recycling.json +1eb435da50adb51433602ea62b9dce553578eefa data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_stairs.json +38727bd7f13b818319fbc8e0c32fdb901b9ffa66 data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_stairs_from_stone_types_autunite_stonecutting.json +9d9992c5487d49b264b33817d5fe68ff0998b181 data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_wall.json +55501543e83ef0225ab9a1a43a183aab2df6c420 data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_wall_from_stone_types_autunite_stonecutting.json +6b1160d1d99257088be280cf3e75a047f35e9ed4 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/black_cloth.json +c1af7f50475be51573c5f57572eec3831073a33b data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/blue_cloth.json +f851e8f840dd9ab4cc8c442b1ec9344b1d949035 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/brown_cloth.json +e784b004df0fff75d820ac59824df36bb27fe9fc data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/cyan_cloth.json +2181ebade82d021b45ca3d08a7ed1713f7fcf2bf data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/gray_cloth.json +b68975a8a0be3b7c75f910d9d978cf651fd83bd0 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/green_cloth.json +95e6f7eea3e340c38fc546030302bfd4d79f57db data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/light_blue_cloth.json +53be998206aaff4861854fea5eec3eb131b03839 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/light_gray_cloth.json +6ae4b584a79916d3a81a9715b0d663821c0c07be data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/lime_cloth.json +6544069252fc84b7ca861b14832bb3351814241e data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/magenta_cloth.json +dfc2c0aed429fd92da9b298daceb67cb8813471d data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/orange_cloth.json +35b8eb5ec8cc5533a512fb983bb161100c935164 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/pink_cloth.json +fba08995866829ec0b153b70dc0f518e49669615 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/purple_cloth.json +711f401d07ffdecd8de2d72a5e2da00ee670de96 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/red_cloth.json +0d947734920dd508d31d0d7659c9cd28792e8e0b data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/white_cloth.json +3b24b8957595f9b81a8bb1e034c3b25600a91ce9 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/yellow_cloth.json +0d4f3a7e8201cb4e0aa9a435915e2313d41c7c19 data/createnuclear/advancement/recipes/building_blocks/small_autunite_bricks_from_stone_types_autunite_stonecutting.json +21ad933339a96f7fb9d35b7af8de57561c9281f1 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_slab.json +8c807c1a3889df15eb039e58df1f7caf23ae1836 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_slab_from_stone_types_autunite_stonecutting.json +8f935c994f8f9656e6699ae995c291cd9fb151c8 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_slab_recycling.json +996932cb30445dd58d79ee0b7458f4640bb96410 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_stairs.json +b591593e24bff98eb83959477db5210389bcff9a data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_stairs_from_stone_types_autunite_stonecutting.json +8a6b40917cfdac102799afb3ecd78f912484aae0 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_wall.json +5ea4ec30969485b3f744eb80b935abc48a9369c4 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_wall_from_stone_types_autunite_stonecutting.json +c4798a992861d2d9262827291f6cfe3673ded43c data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_boots.json +94f3d5d9b4a867532d3860455d60d3e25f281fea data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_chestplate.json +2461ca9ec36bb8403de1587807b941e0a9d983ff data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_helmet.json +920ccecb8560631e711ee27a626f3440a44eae18 data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_leggings.json +3ca63cf9fe6b1dce5cb3f8cb5f7fa11b864f6e28 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_black.json +6b2559a77198a5abe70a6aa6dbbc5b58613cf5fc data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_blue.json +87aa0b6d506a0cee21a6ed3dce90dbe214ff0443 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_brown.json +5259c400523b3be3766b3fa32b8301b515b65a12 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_cyan.json +2957470364f61006a3cd5ed33235c0d60940d53a data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_gray.json +8bb30d26a97e016e679a1f088932ad577a72d4b6 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_green.json +a735a8fa6de3305c168eed05a49fb2df250168a5 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_light_blue.json +bcfe12147e3562b9cea72266552b518d67c402ea data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_light_gray.json +04f481a34309824f27d99268c8c0550848d496d8 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_lime.json +9a7457adab57539a8f1fa95f8effe4d476104abd data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_magenta.json +0c516af3873832c8f58f5e41341055128c12ba3a data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_orange.json +9ed226f75fb1bda1bd205d948540947690f59bea data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_pink.json +cfd97882432fd124d205bda951c10a8828828378 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_purple.json +4cd2964031ea7aa598c76046615a9409acf20fa9 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_red.json +503776c3fb3c586185fbab2fd93569eec6942e9d data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_white.json +9ff7d1db1cbca9c3e6223f576e16439d001fa8c1 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_yellow.json +0634cde728797c0cf5f453968b3f5e06cb0cc1b3 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_black.json +3b665622a12da44fa95bb4e1808c6f77753c71f6 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_blue.json +337a4857f0dd7b4e7019a2d9b2d811cd48597c53 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_brown.json +0334804d09f25f7f8aefdb2b8a5cfc9f9952d04e data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_cyan.json +ea663ccb5a809d02137dfab23f7d8e47d9644f0d data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_gray.json +85578fcfea8887efe33fec9573fb3ded27d88205 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_green.json +ae1e43d527115cbdaf39417643cd3d6e55844f0e data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_light_blue.json +d86cf20c79942fb1b1353843179378f115d1ee60 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_light_gray.json +530f339081fff9745d120ed519fb72d829eefd2c data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_lime.json +0ef89ca66fe0a647a25c9ed170891e7868fe355d data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_magenta.json +b6f41093605e9e882fcbd70b0819eba269de4182 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_orange.json +13a096c0eff9ba37a2749b8879b0fd22239db22f data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_pink.json +a9d30c5ba8ee534b439c711b2dac78b03f418d3f data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_purple.json +2e16cab6b79cb919824262b75f9a422ba24d902c data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_red.json +7cc4adf75f68ecb1f4b5d0422c90cbb2b0ac4614 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_white.json +5fbcb385d91d9555aea624576ed727e4c5917404 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_yellow.json +8c0106583ce64290145b6618d086bfe15a730fd8 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_black.json +61748eb07f544e8ac1e1c224fcad25608e526e1e data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_blue.json +b13e30519f3fa3d292f60318366084c2ce2e481d data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_brown.json +428bdf83e48c535f3c9d97e16a3898a050bd93b3 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_cyan.json +192e3cf91d726d6ee3dbc54ff5a56b0b6722e6c1 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_gray.json +0fa0a5bf7a2e2c9bda0982ba649089426f550867 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_green.json +f2f64c2663778f1ea6a3514e21aa1059cb002fd5 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_light_blue.json +f05848da8d7653c449afb9bce4a77b9e3a53a42d data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_light_gray.json +1f5447b00668d0d4be23eafe420f22d899ca4065 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_lime.json +3b46ffcecb67615bf90011f4224afa37ced86fd8 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_magenta.json +2e50f6ab1b2166560e7f1ce122909f038425bd49 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_orange.json +7f4c3f35180414f1e64d03e9b234e0d8349942e2 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_pink.json +d5ed409bdd9fcdcd9d794d88f84535cbcee292a3 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_purple.json +03d1aa28e7e366c2b71827180adb12e572b6552f data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_red.json +0ba341381abf4c727ecef998be47cc5e51789a1a data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_white.json +33f8caf8631cfc291206dbb1019f444bd51bc22f data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_yellow.json +8c615a1c7e0650743bc941cbfc69a2576335e106 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_black.json +5e6a2f7baf1310fce7c3f36943de4146cfe2df08 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_blue.json +3bc12ed6bd527f448e6897b08214cbf886dc7986 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_brown.json +31c564e6c8aadc68b4b8a69c1db4eb98e526a02f data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_cyan.json +e73f4d2ef9e03df4886ea8fe31367b0f8f18124a data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_gray.json +ab0139c1ef45f3bab4ed0d2e376047246e08e0e8 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_green.json +5b5d178cfabced34b016b0a85655223313625559 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_light_blue.json +78d88294d5256aab1d8fb4cdfaa40854e9d8237c data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_light_gray.json +c2d705571018a86dc0d5a12ed50de43cbb9ee6ef data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_lime.json +df26467204f04a0de033f19832356387ed56e803 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_magenta.json +692f41b65ac1af0370619aefe6eaea02a002f6e3 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_orange.json +352dceb93970e1bb9fb89c3c4ae3fa5c57f7c492 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_pink.json +28987c1c5f347804d2e7f301ee31e3f2904ae48a data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_purple.json +4cd8fc766382327f8d85b962ba24a59e3b4ced4b data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_red.json +cc94ac2250fe5efa6a286d011395f95e043537a9 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_white.json +b250d86b2dc71193ee02f4ae21d587644bdd8482 data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_yellow.json +598c19f86f9c126da3067438d4580eaba1d4c042 data/createnuclear/advancement/recipes/decorations/crafting/raw/raw_thorium_block.json +aa149d3676247b682c6d2e8e02e87f55f8cc3a2f data/createnuclear/advancement/recipes/decorations/crafting/raw_lead_block.json +1f43a98395758f3159e69298327b6546f6576ae8 data/createnuclear/advancement/recipes/decorations/crafting/raw_uranium_block.json +e9881aa1d6af63ece64dbe5a9a7d412de3840c20 data/createnuclear/advancement/recipes/decorations/crafting/reactor/reinforced_glass.json +1ba2c67114313d2e7673fc402d985cdb8e02f1f0 data/createnuclear/advancement/recipes/misc/crafting/biome_irradiation_extractor.json +a1b0ce29f7b72108255deaf87bde4e4cdb878e7b data/createnuclear/advancement/recipes/misc/crafting/enriching_campfire.json +4f06a9916362a31e032d558004c7daca76d50a4e data/createnuclear/advancement/recipes/misc/crafting/lead_ingot_from_decompacting.json +7942dbc0681d08d4eb45fd8c7efe439f45e8749b data/createnuclear/advancement/recipes/misc/crafting/lead_nugget_from_decompacting.json +58995ff78a4223f9aff3f40e055773e704ffa67a data/createnuclear/advancement/recipes/misc/crafting/raw_lead_from_decompacting.json +40bb7871906e8dbd5b59a99fec6a35a84c514a76 data/createnuclear/advancement/recipes/misc/crafting/raw_thorium_from_decompacting.json +01f9b9dd8545687992a425693e25923db093cc7f data/createnuclear/advancement/recipes/misc/crafting/raw_uranium_from_decompacting.json +8b9d3beac96fa049754d6792a18d46fae4e16510 data/createnuclear/advancement/recipes/misc/crafting/reactor_blueprint_item.json +608ba81e528f6e9bdb5e8ab007dcc743397a33f9 data/createnuclear/advancement/recipes/misc/crafting/steel_ingot_from_decompacting.json +92f6a4abe3553b8c5958650d750f65907963015b data/createnuclear/advancement/recipes/misc/crafting/steel_nugget_from_decompacting.json +2a7ad538107f56b60156b505f099c3715bdfdad0 data/createnuclear/advancement/recipes/misc/crafting/thorium_ingot_from_decompacting.json +1ec3c3ffecca3ac43871e7d6c5a920034691d68e data/createnuclear/advancement/recipes/misc/crafting/thorium_nugget_from_decompacting.json +e13e61b6ef24889f1d3d7948892b3e9e3799aa4f data/createnuclear/advancement/recipes/misc/shapeless/reactor_blueprint_item_clear.json +a021646becb7b6411eddd86644e5b17c8365582c data/createnuclear/loot_table/blocks/autunite.json +62b7087350b0a9af9007b848c7f619a730e90693 data/createnuclear/loot_table/blocks/autunite_pillar.json +771b416236bcc21f380e0f312c61803224987616 data/createnuclear/loot_table/blocks/cut_autunite.json +3b81b5b58b7ef985348cf511e609064a7171d7dc data/createnuclear/loot_table/blocks/cut_autunite_bricks.json +feae7c8978bcce63f2eeb2ad6ed6a7ef53cbc13e data/createnuclear/loot_table/blocks/cut_autunite_brick_slab.json +1fa4418198a079b6236b2f3e4b11a7f7d0fc6962 data/createnuclear/loot_table/blocks/cut_autunite_brick_stairs.json +db666ffaca36edc9e246e225f225c1e87604dd88 data/createnuclear/loot_table/blocks/cut_autunite_brick_wall.json +10aff7424eefd85e50269c66e60ae343043193cd data/createnuclear/loot_table/blocks/cut_autunite_slab.json +e6e624e978fdacfa3cdd123d23d021f504308149 data/createnuclear/loot_table/blocks/cut_autunite_stairs.json +f28efa9fb383b86c770b8c7344fc30f6ab9200d3 data/createnuclear/loot_table/blocks/cut_autunite_wall.json +e620244efc3a0de574bc17b9d19882485347bacc data/createnuclear/loot_table/blocks/deepslate_lead_ore.json +26830befeb369026a05725f5d575eb916eb44fe8 data/createnuclear/loot_table/blocks/deepslate_nitrate_ore.json +232adbc9175d5ca16e74957132323cfb25449a75 data/createnuclear/loot_table/blocks/deepslate_thorium_ore.json +d237ef62c175eda7d764c12e1c15dc70954175a7 data/createnuclear/loot_table/blocks/deepslate_uranium_ore.json +76ca23065681dfd7f18dbbc5a65b8ab8bc40c20c data/createnuclear/loot_table/blocks/enriched_soul_soil.json +24bab1e399200ead33320c32ce8b33d4182c1ccc data/createnuclear/loot_table/blocks/enriching_campfire.json +aa8efeb48b11261953f7d90e6d7db38411550694 data/createnuclear/loot_table/blocks/enriching_fire.json +297b7824fc2eea67ef47760da549f73e93424b60 data/createnuclear/loot_table/blocks/layered_autunite.json +efe2ad634ad8b801a8fa69f45516b30157b46771 data/createnuclear/loot_table/blocks/lead_block.json +e2d7ae9213d3a64a68eaf8e549729e62769b05a1 data/createnuclear/loot_table/blocks/lead_ore.json +447982437710862796254645cc6d8b2508f9fe76 data/createnuclear/loot_table/blocks/nitrate_ore.json +7ad41810138d7b55a5d9d0db0956cd255e879632 data/createnuclear/loot_table/blocks/polished_cut_autunite.json +d5fb5ebfe991980abfd6f1932575363d026d8859 data/createnuclear/loot_table/blocks/polished_cut_autunite_slab.json +8205832fc48bd24351b4b433f92a70a533336f48 data/createnuclear/loot_table/blocks/polished_cut_autunite_stairs.json +2c3ca9fb7683d1edfdc2e4fcd4b25ab7f40c3ab6 data/createnuclear/loot_table/blocks/polished_cut_autunite_wall.json +66ab1033aebea1383fe3f09c7468f4cd60d8aa25 data/createnuclear/loot_table/blocks/raw_lead_block.json +7cc60fa9a9bb958907f56b583e27c7f37af2a63e data/createnuclear/loot_table/blocks/raw_thorium_block.json +0998d5a55f2dc10e85e83dd74bd91d4a3913f61f data/createnuclear/loot_table/blocks/raw_uranium_block.json +b0cfc64250ce727ba39807bc1560b36497f294be data/createnuclear/loot_table/blocks/reactor_alarm.json +af059cd55441441329347fbd569245b539b095db data/createnuclear/loot_table/blocks/reactor_casing.json +e76c0b96c978e266f39eca8e46cd5ba2388e1749 data/createnuclear/loot_table/blocks/reactor_controller.json +95a90d9d9a553448c878dfdf4b153ceada923030 data/createnuclear/loot_table/blocks/reactor_cooler.json +daa4fad27f07fd72cb25a524464edea9efe771b7 data/createnuclear/loot_table/blocks/reactor_core.json +1f0c66a193aaddb26626967d16cd8112e18b7383 data/createnuclear/loot_table/blocks/reactor_fluid_input.json +576b0bf970ddbdd11ec06963e1d65e08e63d69e1 data/createnuclear/loot_table/blocks/reactor_frame.json +37af2b0b5eacf53995703344a45fb3f4d0efe1f9 data/createnuclear/loot_table/blocks/reactor_output.json +4d10dc9daa7551a1c4879edbc22f63a8f1d84c73 data/createnuclear/loot_table/blocks/reactor_rod_input.json +03f05a92cf4e1565fe3482f763a1be9e9dd7f088 data/createnuclear/loot_table/blocks/reinforced_glass.json +48c0d8d35932fe1cdb00e5055caa6c1969a8e4cd data/createnuclear/loot_table/blocks/small_autunite_bricks.json +d51f9b307f2986ac086d32f48bd41e6dc4024348 data/createnuclear/loot_table/blocks/small_autunite_brick_slab.json +4014ab450bb5de0522690577486f2fbbc334de9c data/createnuclear/loot_table/blocks/small_autunite_brick_stairs.json +8718c7e7cce27e299611ee34792cdb59f3434e39 data/createnuclear/loot_table/blocks/small_autunite_brick_wall.json +94dc8e72195da5aa505c6d5a3785ccfea30f7c05 data/createnuclear/loot_table/blocks/steel_block.json +10453354af3c17390f7b6eb2eaa7109eae3988c3 data/createnuclear/loot_table/blocks/thorium_block.json +38e9a1df90222fa7b7c717548b68165579789f08 data/createnuclear/loot_table/blocks/thorium_ore.json +dbcee16408e6631009a004edf424bfddc304c640 data/createnuclear/loot_table/blocks/uranium_ore.json +fba1a7bdb0835c034aa5ef52ebf589123d41b33e data/createnuclear/loot_table/entities/irradiated_cat.json +2d8f5d7d7babd2b02ae836846e62daabf84de427 data/createnuclear/loot_table/entities/irradiated_chicken.json +900719d49cec9385da31bb392649c65f4297288c data/createnuclear/loot_table/entities/irradiated_cow.json +f91f43a39c80f583f878ea1a0d944798c05f2388 data/createnuclear/loot_table/entities/irradiated_wolf.json +ef428465f5d04edfb67c7357bef7936e93800cb0 data/createnuclear/recipe/autunite_from_stone_types_autunite_stonecutting.json +5988520980fc9ae12384874425e01110816ea779 data/createnuclear/recipe/autunite_pillar_from_stone_types_autunite_stonecutting.json +663e4794226c60be1efcfd3766c2fd886c61d40f data/createnuclear/recipe/crafting/biome_irradiation_extractor.json +b5fb128b53c749c043861fee9db236aa5ac0e4f5 data/createnuclear/recipe/crafting/enriched_soul_soil.json +cd7d5f4394cd52bc35e4e086c7a2ef658416d9bf data/createnuclear/recipe/crafting/enriching_campfire.json +b1971cfe00916e53eabd9b1d0e2193898747127f data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_boots.json +27ef9ae20c3696f22893fd4df33e56e2d28166f8 data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_chestplate.json +8ec08cbd05abb95f9ef8a0db352aac1286175a61 data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_helmet.json +d51376fb5213a109014687968367e099abc92bed data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_leggings.json +ac1aafbe0f6261f8cf77462fdc7e6ebbffac5431 data/createnuclear/recipe/crafting/lead_ingot_from_decompacting.json +fd535efce0c108d879e5a1f13aface5586fc3127 data/createnuclear/recipe/crafting/lead_nugget_from_decompacting.json +ffa1683a0ba90fa9a0945bbf64947f74e6ee8796 data/createnuclear/recipe/crafting/raw/raw_thorium_block.json +4ecbbca33f6971b904c365a41d67d1f610ca368d data/createnuclear/recipe/crafting/raw_lead_block.json +c9dce33293c71961aea5c4ca04ca837449b87ac7 data/createnuclear/recipe/crafting/raw_lead_from_decompacting.json +a788f72de2d442f171a11a97d5b3d25ebaf48695 data/createnuclear/recipe/crafting/raw_thorium_from_decompacting.json +a8368b7ba6ad28c6073653978c11a17b8e61c009 data/createnuclear/recipe/crafting/raw_uranium_block.json +9a0f17a6a4970542ecf42b775fdcea11f0617c74 data/createnuclear/recipe/crafting/raw_uranium_from_decompacting.json +ed745f567cc3683a58121f3d617ed9d0971a7681 data/createnuclear/recipe/crafting/reactor/reinforced_glass.json +57ce2170813201b6a6c6de35ca8e901c8563894d data/createnuclear/recipe/crafting/reactor_blueprint_item.json +b11529eb646973ecb4096507eff951f55a649a3d data/createnuclear/recipe/crafting/reinforced_glass_bottle.json +000385de7b8a84be8a42ecbc2e486e47978593e6 data/createnuclear/recipe/crafting/steel_ingot_from_decompacting.json +6f664e863b1a0333d16c20d3aacddd54e6f785fb data/createnuclear/recipe/crafting/steel_nugget_from_decompacting.json +19413a166da34c4f7138c758597098d6d2ca6196 data/createnuclear/recipe/crafting/thorium_ingot_from_decompacting.json +7504b59dbc116ff0362a9dc40437b37f56ae19d9 data/createnuclear/recipe/crafting/thorium_nugget_from_decompacting.json +2224ce14a45b2bee57b4390aa5e962c92f223ba1 data/createnuclear/recipe/cut_autunite_bricks_from_stone_types_autunite_stonecutting.json +e0e6e0e4020ea52282b7251c4a5ce9f38ecdc124 data/createnuclear/recipe/cut_autunite_brick_slab.json +02a7ff87c030a7c830141f3dd89aaf549900cf6a data/createnuclear/recipe/cut_autunite_brick_slab_from_stone_types_autunite_stonecutting.json +06eba624cb6116b29074a3fb77390ef3079d600d data/createnuclear/recipe/cut_autunite_brick_slab_recycling.json +2f4e6952fb1718c482ea4b25c640bb902e4a39a4 data/createnuclear/recipe/cut_autunite_brick_stairs.json +8a2a50e11d952d65dd3eec9aa178a46fa7c34aff data/createnuclear/recipe/cut_autunite_brick_stairs_from_stone_types_autunite_stonecutting.json +ec7330ca42e57fe65afa7adc79f0b197b683c5e9 data/createnuclear/recipe/cut_autunite_brick_wall.json +77611fdf35151dd19a3e8fcfb7412ecee27b0716 data/createnuclear/recipe/cut_autunite_brick_wall_from_stone_types_autunite_stonecutting.json +3dab935cb933f719ae1510a793be63c50ade9695 data/createnuclear/recipe/cut_autunite_from_stone_types_autunite_stonecutting.json +359e02720c227b1777749c56f2aecc1dbb11cb5c data/createnuclear/recipe/cut_autunite_slab.json +2a1715abf4ee80450be9828ccfc5a5b8eba88708 data/createnuclear/recipe/cut_autunite_slab_from_stone_types_autunite_stonecutting.json +94601c8648c2eb3e5b31f8d4f92b9c967daced69 data/createnuclear/recipe/cut_autunite_slab_recycling.json +cdd82b6abc937c26877e60a12c4fa4c067bd33d2 data/createnuclear/recipe/cut_autunite_stairs.json +60806f0889257d1def7927f5c81c657e0db7e832 data/createnuclear/recipe/cut_autunite_stairs_from_stone_types_autunite_stonecutting.json +157d6e133873c667a05529ef0d9d1f954d3302b6 data/createnuclear/recipe/cut_autunite_wall.json +e1c81dea36b60f800b9d15deb9da1d436d9e9933 data/createnuclear/recipe/cut_autunite_wall_from_stone_types_autunite_stonecutting.json +9d8784be2feafcacc745f032877ea39ec54d07ba data/createnuclear/recipe/layered_autunite_from_stone_types_autunite_stonecutting.json +3d8239684e4f6d0810e0cc7d52512bee2047ef7c data/createnuclear/recipe/polished_cut_autunite_from_stone_types_autunite_stonecutting.json +5a724d50573d64c00b83c56596473f3444607bbd data/createnuclear/recipe/polished_cut_autunite_slab.json +324ddb54f95fc52ebe1272496103ca1ca2d6c131 data/createnuclear/recipe/polished_cut_autunite_slab_from_stone_types_autunite_stonecutting.json +0b84fc45f98402f0aa890c477fac697807d70486 data/createnuclear/recipe/polished_cut_autunite_slab_recycling.json +92b3b5d69ac2cdabd0169188a8e738b46ae8f568 data/createnuclear/recipe/polished_cut_autunite_stairs.json +a76add5403acbcdda599a3a3a2d7b974578314a8 data/createnuclear/recipe/polished_cut_autunite_stairs_from_stone_types_autunite_stonecutting.json +660c01c1c4cf5d680308d582431efb5d489924df data/createnuclear/recipe/polished_cut_autunite_wall.json +b00d1cbc32c57359488d671a9194eb0bb2d52bf3 data/createnuclear/recipe/polished_cut_autunite_wall_from_stone_types_autunite_stonecutting.json +7fff6e4bad0601b7d9a48d129ff53b6e0abc96fa data/createnuclear/recipe/shapeless/cloth/black_cloth.json +f8c4cd2e4ff4c62135803ee3c4c51d1e82fdd203 data/createnuclear/recipe/shapeless/cloth/blue_cloth.json +b05b6537a3bc762ac6da93d6f33108c828c556d8 data/createnuclear/recipe/shapeless/cloth/brown_cloth.json +f318e27b3a2dd8293a57dedfc8e496b22bb5e595 data/createnuclear/recipe/shapeless/cloth/cyan_cloth.json +c5b6918aa8d64d58fb7d7464b77b7a2669460efc data/createnuclear/recipe/shapeless/cloth/gray_cloth.json +6aa8cda990d9f0cd985b1d435f3c61004cac7677 data/createnuclear/recipe/shapeless/cloth/green_cloth.json +f27884dc693d37338a5c9aba7828c82a3757f1a8 data/createnuclear/recipe/shapeless/cloth/light_blue_cloth.json +a2e2993594e2bc69a3c675d3b527e842dd11b9d5 data/createnuclear/recipe/shapeless/cloth/light_gray_cloth.json +d6ddd657d26a746c99e435c33b5d17beea6f1795 data/createnuclear/recipe/shapeless/cloth/lime_cloth.json +981b5f867fce4c3a7db73ae9c2a994847de1b2c7 data/createnuclear/recipe/shapeless/cloth/magenta_cloth.json +f9c82d6685a542a733fb77dde037df37526469b4 data/createnuclear/recipe/shapeless/cloth/orange_cloth.json +b1fe8aae4120f407d6a2282764668f94b3b835bc data/createnuclear/recipe/shapeless/cloth/pink_cloth.json +a4c27655b9ded8a339ae635f0afe30f839a6f03d data/createnuclear/recipe/shapeless/cloth/purple_cloth.json +40def413fb3ffcfddb3930d75720fc04c162e947 data/createnuclear/recipe/shapeless/cloth/red_cloth.json +d0c9de1945ccb8189c416a836d77f0aa9aba93ae data/createnuclear/recipe/shapeless/cloth/white_cloth.json +5ca79c8e9c5287d9a46bc7defe15c26eb17e3fd8 data/createnuclear/recipe/shapeless/cloth/yellow_cloth.json +3f92b2982573240f019dc370eed41e12ab8963cd data/createnuclear/recipe/shapeless/reactor_blueprint_item_clear.json +43fabb40399e048b2eaeff5f0ea8f2e5d441a8f1 data/createnuclear/recipe/small_autunite_bricks_from_stone_types_autunite_stonecutting.json +4be05821d3cc4ffac867f4bb224d4217aaf45b1d data/createnuclear/recipe/small_autunite_brick_slab.json +da40f5d524c9440d7d1300f543726f77b6fac1e0 data/createnuclear/recipe/small_autunite_brick_slab_from_stone_types_autunite_stonecutting.json +c05dcc6178e1be10c8a8a7f7b9aff7ff47775e16 data/createnuclear/recipe/small_autunite_brick_slab_recycling.json +08e264e297d18de78a3fae40e529043c515e134a data/createnuclear/recipe/small_autunite_brick_stairs.json +e9950d7f4f382bf21c9b3817ccd4123438284694 data/createnuclear/recipe/small_autunite_brick_stairs_from_stone_types_autunite_stonecutting.json +58733c26e138219a3faacab87f5e19277ef99217 data/createnuclear/recipe/small_autunite_brick_wall.json +c094aebdafd05ba86f8accd0e65cf0318771efda data/createnuclear/recipe/small_autunite_brick_wall_from_stone_types_autunite_stonecutting.json +455c1a4cabfe6c868cf66879f3cc83c9676e67f1 data/createnuclear/recipe/smithing/default_anti_radiation_boots_black.json +62b869fe6e8bd233199c93fdb5c38dbac45991a4 data/createnuclear/recipe/smithing/default_anti_radiation_boots_blue.json +995ec20410876d78b05c87bbb73f66623518e01f data/createnuclear/recipe/smithing/default_anti_radiation_boots_brown.json +2248d7005e41a3720ad8dedd59e28482ffa9d8f5 data/createnuclear/recipe/smithing/default_anti_radiation_boots_cyan.json +c95838f6ca7cff596b2e82d196d08d4d2a2bae9d data/createnuclear/recipe/smithing/default_anti_radiation_boots_gray.json +1713908d4df8fda05698b6611dd4cf362bb44eb3 data/createnuclear/recipe/smithing/default_anti_radiation_boots_green.json +897a6756fae6f3ac634303fef43aa56780b6d767 data/createnuclear/recipe/smithing/default_anti_radiation_boots_light_blue.json +d81c7107b60162b3fdbd1e38ed3ce9c91e4b399e data/createnuclear/recipe/smithing/default_anti_radiation_boots_light_gray.json +05f02070d547ee54a54b1cc3f0e8ecca72d64a87 data/createnuclear/recipe/smithing/default_anti_radiation_boots_lime.json +edb2956fa4829364c2447a82ec1807994b15afbb data/createnuclear/recipe/smithing/default_anti_radiation_boots_magenta.json +8c4fb4caec2b0ec02f1b59f4721ef7b122318aae data/createnuclear/recipe/smithing/default_anti_radiation_boots_orange.json +3c62d21cec6eb7bcb0ba824c35b7de83b3ddf854 data/createnuclear/recipe/smithing/default_anti_radiation_boots_pink.json +ab4b28fa8e3997bd6dd32200c39610e7062259cc data/createnuclear/recipe/smithing/default_anti_radiation_boots_purple.json +e058bf62eb7aeabc95b871955b213f74e195580c data/createnuclear/recipe/smithing/default_anti_radiation_boots_red.json +744ab66e05200b6ed3915f78dce69799767b6e9b data/createnuclear/recipe/smithing/default_anti_radiation_boots_white.json +7d73b19dfeff5e641229ff1212b126ae42f8e7c6 data/createnuclear/recipe/smithing/default_anti_radiation_boots_yellow.json +2cbcb5bdbba6500013898b349c83830b1445ede5 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_black.json +ccdfa65039670d6a6dc1918c90867d97e9470c03 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_blue.json +2bdd9f08f962a70afa1f6ca5c2372eadabacb107 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_brown.json +651cb47fce3b9ac62d20e6efab8d9b00ee796a96 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_cyan.json +0feb1a7568c31017fc0586ca53a922aa6a122215 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_gray.json +259a6d9128436b9e70df8d5ead9d3e3e23f647b3 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_green.json +678e2f3a9250b7535b2d057028ab6af3570333c6 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_light_blue.json +72e9dc574772f1f246e3b83089c4904c74de1424 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_light_gray.json +118b5bb07f4946774cbf00308035e0522babdb6e data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_lime.json +9662a1955ca4f7356371ea8297922b63793a749b data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_magenta.json +b6f240581f49537be23a311b91275dd7ca1e6102 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_orange.json +e394cc65f4d4a9a94d1d493f8fb6cd034543a7b2 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_pink.json +14b175b01d614da3ea1d68268cf472a26f60ec53 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_purple.json +910cc62970999df0e3dac232b8e0d9bf2b37b298 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_red.json +cfba1a03a4e4e14ae720b14c0ec68387aeb7c623 data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_white.json +92a5f3e1a5746a35778a528b12afe0829276631e data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_yellow.json +d0f31c6d2372decaf038b8121d2a08043cd14766 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_black.json +c856a5ae7f3443b8916753d56618438e637a9b64 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_blue.json +af5b6fe73992096c826c61a292c953b595503149 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_brown.json +dea971c15476de2a2eb1539f8e6a3e4d507f5ad9 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_cyan.json +dd7823270a536f05747d1cb2dda4f009f9c40bf2 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_gray.json +67153bb3cba92f930edadd25ddf2a2cd545a97b3 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_green.json +4ee88bd63de1f325d5e488321c82cbbad4b88d86 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_light_blue.json +690ece4561cc80d93722bd1ea50ba54f6eee7373 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_light_gray.json +2387509ea5126276b746c96092fbf8cc944fc38c data/createnuclear/recipe/smithing/default_anti_radiation_helmet_lime.json +efe6118d71fbf66869ea57086770d687b0906dd8 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_magenta.json +43ab68a61e11682c03a913afe8afb401eb0c9df6 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_orange.json +2fa9b4664c7f2f2c7ec3bf1e5d89e4dc18a18abd data/createnuclear/recipe/smithing/default_anti_radiation_helmet_pink.json +87ee22892f66dda2b417a86caa07b8ba17c5d473 data/createnuclear/recipe/smithing/default_anti_radiation_helmet_purple.json +be356c1e723bd96f061d3f403f46fd6b057efecb data/createnuclear/recipe/smithing/default_anti_radiation_helmet_red.json +889a7e0d7fe6c5a271e464ab681f93a2887bb26f data/createnuclear/recipe/smithing/default_anti_radiation_helmet_white.json +b57256fdb8432680bd88786d94b27b9a4360c66c data/createnuclear/recipe/smithing/default_anti_radiation_helmet_yellow.json +bdfb29a3c2bc2d987eb8efd1d54357723207da02 data/createnuclear/recipe/smithing/default_anti_radiation_leggings_black.json +4b68ba7f37e0d9896db566f618cebd505f8678fb data/createnuclear/recipe/smithing/default_anti_radiation_leggings_blue.json +975cc6316dc20c5a0e34778d78f7e3b6a72bbc3e data/createnuclear/recipe/smithing/default_anti_radiation_leggings_brown.json +24ea77f33314e43b2af918845f9e4c484ef7d375 data/createnuclear/recipe/smithing/default_anti_radiation_leggings_cyan.json +439c29e71a50b9fdb66cab683000eede2840057e data/createnuclear/recipe/smithing/default_anti_radiation_leggings_gray.json +6145411c4fd8b2a1b9f15c5578dea3b2244f86dc data/createnuclear/recipe/smithing/default_anti_radiation_leggings_green.json +a8b5876c604baf3dc422edccb4a6322e9df58957 data/createnuclear/recipe/smithing/default_anti_radiation_leggings_light_blue.json +b1c1761bb9c39aa8921c8b850dbd7207d0889467 data/createnuclear/recipe/smithing/default_anti_radiation_leggings_light_gray.json +1408f3fcb561ec0ad24fab104b74333dc8bb6d2e data/createnuclear/recipe/smithing/default_anti_radiation_leggings_lime.json +ec054047573c8fe78d2a1100abef7145fe858860 data/createnuclear/recipe/smithing/default_anti_radiation_leggings_magenta.json +7e4b403bd001455a28de36d6fd49310d5cb82b65 data/createnuclear/recipe/smithing/default_anti_radiation_leggings_orange.json +e1a1ee42e3be74142c735f7925ec79b04d964768 data/createnuclear/recipe/smithing/default_anti_radiation_leggings_pink.json +b9acee8e2473c3340467da385099fd5b6b49b74f data/createnuclear/recipe/smithing/default_anti_radiation_leggings_purple.json +bb29ba0abd11f915b69b8cc91c28e62a9eed517b data/createnuclear/recipe/smithing/default_anti_radiation_leggings_red.json +fdace7ee58d9860d4549876326a44645f9df2a10 data/createnuclear/recipe/smithing/default_anti_radiation_leggings_white.json +15960ecb10eeaba53bc6fe3dcc382853c5795256 data/createnuclear/recipe/smithing/default_anti_radiation_leggings_yellow.json +a7d4278d8a39649c8b658ad2f3f1d092cb012bdf data/createnuclear/tags/block/enriching_fire_base_blocks.json +509b5baa813ae0dc3345fd97754e4088132359ec data/createnuclear/tags/block/fan_processing_catalysts/enriched.json +bc8701774f57ab000a8f0f1d390702175a6cdbb8 data/createnuclear/tags/block/fan_processing_catalysts/snow_powder.json +ccbc67cba973a8e1e43d0166ddfa5645f6a82aea data/createnuclear/tags/entity_type/irradiated_immune.json +410aa6d101788f25baa176741887c6f314006f29 data/createnuclear/tags/fluid/nitrogen.json +dd07a117bf2a657aba3d776ee718829150a1c0af data/createnuclear/tags/fluid/thorium.json +bfd5a561b60a7d59d7f7c248ec75e3571a0f2fed data/createnuclear/tags/fluid/uranium.json +bce34f53cb2d00f7dee84683e8fdd429dabbcc1d data/createnuclear/tags/item/anti_radiation_armor.json +b3f8c7d4cc47db1954a7470d37e5e4e6549c9480 data/createnuclear/tags/item/anti_radiation_helmet.json +2e4d08932c4a84863f0198eb2845f80d8fda1221 data/createnuclear/tags/item/cloth.json +8e6598f14a72a61cbe1e5ed2aaea229fb2dd74e6 data/createnuclear/tags/item/cooler.json +d534438c9314e8b014bf1796060dd801f4ef4d4e data/createnuclear/tags/item/fuel.json +53e435b1776a11737c64eac604fda6cd48acfc4e data/createnuclear/tags/item/stone_types/autunite.json +35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/createnuclear/tags/item/thorium_ores.json +d8d6ad7a4fc31fd68a98b368207c359fb610f417 data/create/tags/block/safe_nbt.json +75f0600da4891d0f4a3329fb44cac6c4945a0b49 data/c/tags/block/glass_blocks.json +1fd17be1d553e7ddf20494ee1e98084f02137cc8 data/c/tags/block/ores.json +925cb97bc13b3122fe17e59ff3ec2fe4d1eaacd5 data/c/tags/block/ores/lead.json +1ad062f84e124267bb3aae3add3a4e5265a4f8d7 data/c/tags/block/ores/nitrate.json +3f665c928bcdfaa68700d1da7a28fddcbb7bf802 data/c/tags/block/ores/thorium.json +bad88bea18fec41c7ad6fa4d396feacc0346a137 data/c/tags/block/ores/uranium.json +4f1ebc0bb505bc510c52671c5935494270ec7008 data/c/tags/block/ores_in_ground/deepslate.json +a04457046c7b0dc46d430af61f83518a84a508d2 data/c/tags/block/ores_in_ground/stone.json +1f9b1d0abae115bee9a7d66e47f36a0b651d555a data/c/tags/block/storage_blocks.json +a7258ae3454252e874b324fbd81b880ce52759c4 data/c/tags/block/storage_blocks/lead.json +2b32fe875f887d4a406700d35e0fe5a93548ebb7 data/c/tags/block/storage_blocks/raw_lead.json +725644962932169e20d6f2726e69af199ce3800c data/c/tags/block/storage_blocks/raw_thorium.json +0aafd338eaffcc3f48fb8dc9d18fc969318b06e0 data/c/tags/block/storage_blocks/raw_uranium.json +f8074cdbc6e2b560acb4e9da953b23f9825486a6 data/c/tags/block/storage_blocks/steel.json +baae2dfd7e19770072d6261ec68ce157a32be80c data/c/tags/block/storage_blocks/thorium.json +a63487094743744be756ad497f483fcd4d11e9bc data/c/tags/fluid/uranium.json +bce34f53cb2d00f7dee84683e8fdd429dabbcc1d data/c/tags/item/armors.json +e15fb3153f19574ecf55a117c026f6bf028f3a87 data/c/tags/item/armors/boots.json +fb238dbddaf54871f03731ee7cce881af0932459 data/c/tags/item/armors/chestplates.json +b3f8c7d4cc47db1954a7470d37e5e4e6549c9480 data/c/tags/item/armors/helmets.json +9f9c6b5fe521e31527d238cd230e6f3ef689857f data/c/tags/item/armors/leggings.json +419d05292cb4947015b5320c991500e5a51f5466 data/c/tags/item/buckets/nitrogen.json +c53aa7c19dc2c02afdab4bc7e3188ca2b2224af6 data/c/tags/item/buckets/thorium.json +9ac9f967f480bbbe186815331a7e1771c8feea57 data/c/tags/item/buckets/uranium.json +349b8e846393ae82a9117cd0534323bd79fc8f01 data/c/tags/item/dusts.json +25c93720c5221fac9aeb0ae47182ef59e0a0c2bb data/c/tags/item/dusts/coal.json +d6176bfd8cf296e3d5b5601ff2da8fc59620a092 data/c/tags/item/dusts/thorium.json +69b53861489d10b3a836be9812af97c999833470 data/c/tags/item/dusts/uranium.json +75f0600da4891d0f4a3329fb44cac6c4945a0b49 data/c/tags/item/glass_blocks.json +69b0ac78e6b1f46e527de8e63aba797c335290f9 data/c/tags/item/ingots.json +30fa647448df4131c1d6460756f18583a493ee31 data/c/tags/item/ingots/lead.json +24bc6e0cdae825d9e5d1500567ae81d83c15a88d data/c/tags/item/ingots/steel.json +a50840c5dc4023ab62b7faa86a5fd9f032a50caf data/c/tags/item/ingots/thorium.json +a77ba3f79cd096f38bd53b5f1b6a5696b864e9df data/c/tags/item/nuggets.json +41ff866ec94383906342a0d1594554e3063b9d0f data/c/tags/item/nuggets/lead.json +1ec402fda0c91947be220066973f79f3e522663f data/c/tags/item/nuggets/steel.json +31d6f68b8cbb51e44700987c1b242a855e120b33 data/c/tags/item/nuggets/thorium.json +1fd17be1d553e7ddf20494ee1e98084f02137cc8 data/c/tags/item/ores.json +925cb97bc13b3122fe17e59ff3ec2fe4d1eaacd5 data/c/tags/item/ores/lead.json +1ad062f84e124267bb3aae3add3a4e5265a4f8d7 data/c/tags/item/ores/nitrate.json +3f665c928bcdfaa68700d1da7a28fddcbb7bf802 data/c/tags/item/ores/thorium.json +bad88bea18fec41c7ad6fa4d396feacc0346a137 data/c/tags/item/ores/uranium.json +494676a581ac065ec9c0802aa63c30acdd72be5b data/c/tags/item/raw_materials.json +610ed700de0886bcb4b1c90100c35f3034c53940 data/c/tags/item/raw_materials/lead.json +61f6f1f4b16790c36a45f769141900772ce4529a data/c/tags/item/raw_materials/thorium.json +03a88f0d9f44d3c338b82bf92b22a14dec490bef data/c/tags/item/raw_materials/uranium.json +494676a581ac065ec9c0802aa63c30acdd72be5b data/c/tags/item/raw_ores.json +5b4967b0dfcb637e942604f39d4d9179fca5b776 data/c/tags/item/rods.json +1f9b1d0abae115bee9a7d66e47f36a0b651d555a data/c/tags/item/storage_blocks.json +a7258ae3454252e874b324fbd81b880ce52759c4 data/c/tags/item/storage_blocks/lead.json +2b32fe875f887d4a406700d35e0fe5a93548ebb7 data/c/tags/item/storage_blocks/raw_lead.json +725644962932169e20d6f2726e69af199ce3800c data/c/tags/item/storage_blocks/raw_thorium.json +0aafd338eaffcc3f48fb8dc9d18fc969318b06e0 data/c/tags/item/storage_blocks/raw_uranium.json +f8074cdbc6e2b560acb4e9da953b23f9825486a6 data/c/tags/item/storage_blocks/steel.json +baae2dfd7e19770072d6261ec68ce157a32be80c data/c/tags/item/storage_blocks/thorium.json +8875ba7215b30d75573e3dcfe46e0b690b1d7f2f data/minecraft/tags/block/azalea_root_replaceable.json +e84d8e1fa924bec3e226b8917b4973b9629a5f52 data/minecraft/tags/block/campfires.json +3206babfa42429478935375acd710b4028884941 data/minecraft/tags/block/dragon_transparent.json +8875ba7215b30d75573e3dcfe46e0b690b1d7f2f data/minecraft/tags/block/dripstone_replaceable_blocks.json +3206babfa42429478935375acd710b4028884941 data/minecraft/tags/block/fire.json +75f0600da4891d0f4a3329fb44cac6c4945a0b49 data/minecraft/tags/block/impermeable.json +8875ba7215b30d75573e3dcfe46e0b690b1d7f2f data/minecraft/tags/block/lush_ground_replaceable.json +e84d8e1fa924bec3e226b8917b4973b9629a5f52 data/minecraft/tags/block/mineable/axe.json +fe184f6ffab0018aab2e2b54341e24d0efbc960b data/minecraft/tags/block/mineable/pickaxe.json +a7d4278d8a39649c8b658ad2f3f1d092cb012bdf data/minecraft/tags/block/mineable/shovel.json +8875ba7215b30d75573e3dcfe46e0b690b1d7f2f data/minecraft/tags/block/moss_replaceable.json +af6dc9f8e98b963b468d2ec348343783ec30be1d data/minecraft/tags/block/needs_diamond_tool.json +1fd17be1d553e7ddf20494ee1e98084f02137cc8 data/minecraft/tags/block/needs_iron_tool.json +70955c444f864b4cf76dc7494195b95cec0c0775 data/minecraft/tags/block/slabs.json +f730ea13c5c0e367d6108fee0d47d10e8c39f3f7 data/minecraft/tags/block/stairs.json +a584f04787aadc06749c484b53947d4f78fccb96 data/minecraft/tags/block/walls.json +2535c56fd6376328fbca0528562ecc2046a3b655 data/minecraft/tags/entity_type/fall_damage_immune.json +a63487094743744be756ad497f483fcd4d11e9bc data/minecraft/tags/fluid/lava.json +9b1c04e4516407eb6df9f1262fd73a71605f3bb1 data/minecraft/tags/fluid/water.json +70955c444f864b4cf76dc7494195b95cec0c0775 data/minecraft/tags/item/slabs.json +f730ea13c5c0e367d6108fee0d47d10e8c39f3f7 data/minecraft/tags/item/stairs.json +a584f04787aadc06749c484b53947d4f78fccb96 data/minecraft/tags/item/walls.json diff --git a/src/generated/resources/.cache/708b1206ce73e235f43eb2a5fd72b93671cfba4e b/src/generated/resources/.cache/708b1206ce73e235f43eb2a5fd72b93671cfba4e index e0827fb..e27c35b 100644 --- a/src/generated/resources/.cache/708b1206ce73e235f43eb2a5fd72b93671cfba4e +++ b/src/generated/resources/.cache/708b1206ce73e235f43eb2a5fd72b93671cfba4e @@ -1,7 +1,9 @@ -// 1.21.1 2025-06-28T12:05:07.4747493 createnuclear's mechanical crafting recipes +// 1.21.1 2026-08-15T15:38:30.2786335 createnuclear's mechanical crafting recipes 6faa6bf8a64d224f96053a4a7edba2231f680267 data/createnuclear/recipe/mechanical_crafting/graphite_rod.json +980c532ce8f536f3283efd0252cee7f86d1c7ee9 data/createnuclear/recipe/mechanical_crafting/reactor_alarm.json 8ef4ccba90238cd89d51b3a320f4dac756ba0180 data/createnuclear/recipe/mechanical_crafting/reactor_controller.json 666c74e8c0983152267a4f3ed100767717834742 data/createnuclear/recipe/mechanical_crafting/reactor_cooler.json 69f0e1c6a8a2edc51d52f72e409865f800e2f2cb data/createnuclear/recipe/mechanical_crafting/reactor_core.json -42caf3612995a08fc45f930bedca61eb093ee29f data/createnuclear/recipe/mechanical_crafting/reactor_frame.json +9dc7a4bc990d226c01514ca717deb6d7db311208 data/createnuclear/recipe/mechanical_crafting/reactor_frame.json +488f05c123ef053512e8244835ae51708cfaac66 data/createnuclear/recipe/mechanical_crafting/thorium_rod.json b34105d0ae8b7d1ad137dfe3903dd47fa69481d9 data/createnuclear/recipe/mechanical_crafting/uranium_rod.json diff --git a/src/generated/resources/.cache/9732d134b83831a56ebe496b16cec71e982962ee b/src/generated/resources/.cache/9732d134b83831a56ebe496b16cec71e982962ee deleted file mode 100644 index f90db84..0000000 --- a/src/generated/resources/.cache/9732d134b83831a56ebe496b16cec71e982962ee +++ /dev/null @@ -1,563 +0,0 @@ -// 1.21.1 2025-12-13T13:14:00.8908781 Registrate Provider for createnuclear [Registries, Data Maps, Recipes, Advancements, Loot Tables, Tags (enchantments), Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), generic_server_provider, Blockstates, Item models, Lang (en_us/en_ud), generic_client_provider] -0b2c76c9cff305eacfdfb57c4b703f94ca6dc903 assets/createnuclear/blockstates/autunite.json -5d06bc544bcbeb7443178d66955bb5101cf696da assets/createnuclear/blockstates/autunite_pillar.json -5b375444ac5057e63776f4991589c57824574b4a assets/createnuclear/blockstates/cut_autunite.json -f402fda858988cbb5e1a6a623cb15a6c76ac7f54 assets/createnuclear/blockstates/cut_autunite_bricks.json -b88d65e7a3393caeaed8d504bf6c4615767371aa assets/createnuclear/blockstates/cut_autunite_brick_slab.json -7f788334258cfb67dfbf716dbaf1b126376d1a14 assets/createnuclear/blockstates/cut_autunite_brick_stairs.json -7bfc6778893ef6552c10e17e3489e201758d3a75 assets/createnuclear/blockstates/cut_autunite_brick_wall.json -1e246d1862a801b2253595d7fac7717a0110ce79 assets/createnuclear/blockstates/cut_autunite_slab.json -56c308e675a047a3d28757377e61e5f79c6384e3 assets/createnuclear/blockstates/cut_autunite_stairs.json -98d386985f7c185f1acab25b9d606828f788769f assets/createnuclear/blockstates/cut_autunite_wall.json -5cf183e5277aea7ac5eb2bfa88737db909c6244d assets/createnuclear/blockstates/deepslate_lead_ore.json -a6f90dfcfc0659663335d4c80129ce41d0c8e47a assets/createnuclear/blockstates/deepslate_uranium_ore.json -e11c7fa5830b0877af69bb18e650d2b1e6f90027 assets/createnuclear/blockstates/enriched_soul_soil.json -f6b762b1e80656d932e990210b43e4bfb209e4d8 assets/createnuclear/blockstates/enriching_campfire.json -41d2222cb4f17c8c035f1937873518ad2adca3db assets/createnuclear/blockstates/enriching_fire.json -98dd6f667ccef1f8f1d332b42b146a6c0bbfb0db assets/createnuclear/blockstates/layered_autunite.json -f10bbdbab6112c58bebf2d98dc0ed3eb9370c09c assets/createnuclear/blockstates/lead_block.json -300b8a29d6a440a60320133481041671dde65448 assets/createnuclear/blockstates/lead_ore.json -1eed8de7f7b90d46d3e4fb6a0e7e9abf10a8a78f assets/createnuclear/blockstates/polished_cut_autunite.json -462d22ea4a021cc368721fdb841c8a9b9176c06d assets/createnuclear/blockstates/polished_cut_autunite_slab.json -76a9a39503654b94cbe01e249292ed280446bbb6 assets/createnuclear/blockstates/polished_cut_autunite_stairs.json -f628f8c7aa1e150ad2b5a3ce87dbe7f00b462e74 assets/createnuclear/blockstates/polished_cut_autunite_wall.json -8195d52278bf58414faaaec6067905635aaa29d5 assets/createnuclear/blockstates/raw_lead_block.json -63aaf78c3e0c16c2f37b069c5392e3d1a93ac058 assets/createnuclear/blockstates/raw_uranium_block.json -0fbc9288622efc18fe39b6c8ba89e7e2281dee26 assets/createnuclear/blockstates/reactor_casing.json -60ca260d5b5bcd975c0a3918b461748786cde95e assets/createnuclear/blockstates/reactor_controller.json -3c259041f317bb8868fb4f177c457fc12b8d28f5 assets/createnuclear/blockstates/reactor_cooler.json -3cced3f7d35371f1881b0485ee324788adcd2c74 assets/createnuclear/blockstates/reactor_core.json -ff68065029f7d47434aaf3f60e5ec3319302d2d8 assets/createnuclear/blockstates/reactor_frame.json -797bb3045272b742be75c5dc1a511a1c2acaa877 assets/createnuclear/blockstates/reactor_input.json -36ee5c127b0548502d15bc16a638a5bac40df1b6 assets/createnuclear/blockstates/reactor_output.json -f7504d5f748fe938bf07d2eb5d0ba46bbfa0499d assets/createnuclear/blockstates/reinforced_glass.json -664db32ecb461bb1a8774d71d4d7168cfa56803c assets/createnuclear/blockstates/small_autunite_bricks.json -d4df48b7d5c38d7cf0b9347c196024e11497ca00 assets/createnuclear/blockstates/small_autunite_brick_slab.json -b9c915389ea6cf8338d20c48e908591f8baa2108 assets/createnuclear/blockstates/small_autunite_brick_stairs.json -7407bdb3685a15929a770b144d50cdc67c9c776f assets/createnuclear/blockstates/small_autunite_brick_wall.json -57c846a957e9250bc45f2f1091bf3f78b2a77344 assets/createnuclear/blockstates/steel_block.json -de2884054a21315d8b167f64b206be331d388420 assets/createnuclear/blockstates/uranium.json -4557f548df100ae1d05e3b5711797225f6a39673 assets/createnuclear/blockstates/uranium_ore.json -6cec7e7c59c8c220b545ff6377af096d5dec4a3f assets/createnuclear/lang/en_ud.json -6b78948d4ac59999cf46ada012e06dba257727fd assets/createnuclear/lang/en_us.json -a8495d2cd5e38213683becaf1c84b2852f8b06f5 assets/createnuclear/models/block/autunite_natural_0.json -29394a22ee8655dc22ea51563411505fbcfd2dab assets/createnuclear/models/block/autunite_natural_1.json -9e4f83de1ca7a9ab5363f43fc7c3f7f4ec6164d5 assets/createnuclear/models/block/autunite_natural_2.json -8241a75180c5634be558974bc09f15600261f67f assets/createnuclear/models/block/autunite_natural_3.json -2f6b85682c569527f9f538dae16526505ce5655a assets/createnuclear/models/block/autunite_pillar.json -4a04692c39cfad137877258b4443eb4bf5298423 assets/createnuclear/models/block/autunite_pillar_horizontal.json -a48d579af38beab6fc87d3b02a7ed902b25bdf16 assets/createnuclear/models/block/cut_autunite.json -4d49f9151293582741edc0d935f3130547cf5360 assets/createnuclear/models/block/cut_autunite_bricks.json -6729240e3a6cbda812d3feb8e287f743bd6b6de5 assets/createnuclear/models/block/cut_autunite_bricks_wall_post.json -244715a4f0f6a21d055b1de3307c303a5a885c1d assets/createnuclear/models/block/cut_autunite_bricks_wall_side.json -f8d6743895a633a45eb0c565cb7f79aae9172175 assets/createnuclear/models/block/cut_autunite_bricks_wall_side_tall.json -c470ac7f3b34c8da456f221d81b45292f0657e36 assets/createnuclear/models/block/cut_autunite_brick_slab.json -d4084e8b32d197db311b575a06023bb5fd5d8aba assets/createnuclear/models/block/cut_autunite_brick_slab_top.json -e4a795c7efcfa306ac6772e2b8a23a3afc52c0ec assets/createnuclear/models/block/cut_autunite_brick_stairs.json -90a9c051a0c72398a1f052542620029275e6a676 assets/createnuclear/models/block/cut_autunite_brick_stairs_inner.json -4bb891d8f069cf043de74c0cc9d16fcbcb49ee07 assets/createnuclear/models/block/cut_autunite_brick_stairs_outer.json -d9ae523c08cbbe274a598736a8a9fd510d78d484 assets/createnuclear/models/block/cut_autunite_slab.json -14043cfcb42894ebb0db2501929ba4cae9d8bd7d assets/createnuclear/models/block/cut_autunite_slab_top.json -f66edf8ef01d16ee116ac71e742bea54e98e1724 assets/createnuclear/models/block/cut_autunite_stairs.json -e1e1e4bff55028860d776d8ecb992547fa12b1b5 assets/createnuclear/models/block/cut_autunite_stairs_inner.json -6d1c45b12d9e783e63849d15aa29d507266bd1bb assets/createnuclear/models/block/cut_autunite_stairs_outer.json -05c9937ab6b920dfbbab6c78d115cc0bff6b8d22 assets/createnuclear/models/block/cut_autunite_wall_post.json -baced15580735dd63848a96763f8c7ffe61f3376 assets/createnuclear/models/block/cut_autunite_wall_side.json -cd15b5be0dca5f621266b157b424ac37dac859dd assets/createnuclear/models/block/cut_autunite_wall_side_tall.json -9a589577d80aa23ac97312bda605b5512eff5167 assets/createnuclear/models/block/deepslate_lead_ore.json -6793dd91b730f4c9abea29215de16cd0751d8cbd assets/createnuclear/models/block/deepslate_uranium_ore.json -e1b8fdc0555a1fdabda54f66cca868e444d1110b assets/createnuclear/models/block/enriched_soul_soil.json -8408a3894e9ca6e45e738b81f0a1932a0b2f86a5 assets/createnuclear/models/block/layered_autunite.json -fd642aefed8f59f5575c96ad1a0251e7773f3909 assets/createnuclear/models/block/lead_block.json -c9757e3fd9841ee17366b1d88563df6ea8106513 assets/createnuclear/models/block/lead_ore.json -460e9ac2c0a90607b74afc5823b737a2867a35e3 assets/createnuclear/models/block/polished_cut_autunite.json -8d0e97cda9e4098e0aa8dca93445d3b52150dcfa assets/createnuclear/models/block/polished_cut_autunite_slab.json -4fa87093074c0a325ea50ab2d3c9725a90a11e1c assets/createnuclear/models/block/polished_cut_autunite_slab_double.json -6aab787de0caf399f8b76b94c64d850e5d55c757 assets/createnuclear/models/block/polished_cut_autunite_slab_top.json -0057844c28c996dceebfc28e95e0f022a26db0aa assets/createnuclear/models/block/polished_cut_autunite_stairs.json -741e53f404a88b4aa7bf6e8246bbe3cf1d6404b5 assets/createnuclear/models/block/polished_cut_autunite_stairs_inner.json -a251d75552efea796382a4124659f9d39606461b assets/createnuclear/models/block/polished_cut_autunite_stairs_outer.json -3fcae9cce1819111bdab42b8b92a1468394db3b1 assets/createnuclear/models/block/polished_cut_autunite_wall_post.json -ad989d89e7b80a30e0860fb0f1418013fe3355d2 assets/createnuclear/models/block/polished_cut_autunite_wall_side.json -b950ac6ca2df77ffe3abd02e13c38567602e5536 assets/createnuclear/models/block/polished_cut_autunite_wall_side_tall.json -cf8b4d604330762358b21b6e079aaab1eb2987f4 assets/createnuclear/models/block/raw_lead_block.json -561c9f9a4e153fc648a3c7224812c71c8ac2da5c assets/createnuclear/models/block/raw_uranium_block.json -7cdeee7f4740b6a86802354534be24dbb251e211 assets/createnuclear/models/block/reinforced_glass.json -e94d3eb865d17234b18241d89acdec2b10a1d21a assets/createnuclear/models/block/small_autunite_bricks.json -0632d6a6ba895efbfa6a347c9693240cc601e114 assets/createnuclear/models/block/small_autunite_bricks_wall_post.json -093bb2418968291015e9d3122755af3fd0b948d4 assets/createnuclear/models/block/small_autunite_bricks_wall_side.json -5a9a262da20c1b7053276c444bff017e73c923c9 assets/createnuclear/models/block/small_autunite_bricks_wall_side_tall.json -2d0c4071223fd38069cfdac403b33bd2925d6750 assets/createnuclear/models/block/small_autunite_brick_slab.json -496e7d40f96d28015e8dd1c787d4620e090ad965 assets/createnuclear/models/block/small_autunite_brick_slab_top.json -b9b18c9a633527a817ba9745a818980ff35836b5 assets/createnuclear/models/block/small_autunite_brick_stairs.json -072d33301f6734db5108d78731686fc34b32c6c3 assets/createnuclear/models/block/small_autunite_brick_stairs_inner.json -f99b30bd0cb3a8b78ed88a3a17b35b512c69ee06 assets/createnuclear/models/block/small_autunite_brick_stairs_outer.json -47f627eaccbd07bf81d1c45f95ebcc88994ad757 assets/createnuclear/models/block/steel_block.json -d234edb3b6bc81b7300ee65722973b66db0b82d9 assets/createnuclear/models/block/uranium.json -a4d5ee44c830e329034a46792280edea53343034 assets/createnuclear/models/block/uranium_ore.json -fba1c32ae3c38d735ebb0b4c3912afc8f9e9cde4 assets/createnuclear/models/item/anti_radiation_boots.json -29394a22ee8655dc22ea51563411505fbcfd2dab assets/createnuclear/models/item/autunite.json -30b11d8da5d02a3e9cebb739b3b9efbee087573c assets/createnuclear/models/item/autunite_pillar.json -f8e44e53a7bc368d4c159769bb071eef6d28d856 assets/createnuclear/models/item/black_anti_radiation_chestplate.json -82a63e5c93daac9c5430ae77aa8d10b1bddbc2c7 assets/createnuclear/models/item/black_anti_radiation_helmet.json -2d0a3f0d2dd0fab5b73c7b8291a5eb3a7921157a assets/createnuclear/models/item/black_anti_radiation_leggings.json -3036f3b383b40ca2021856366cd0f01cb279285b assets/createnuclear/models/item/black_cloth.json -288c9245496eb0020ace0481a4d4ac26df876063 assets/createnuclear/models/item/blue_anti_radiation_chestplate.json -b8574d7ee3d3e733dab79700062554cf4b58bd6f assets/createnuclear/models/item/blue_anti_radiation_helmet.json -ed88d15d2f1a4af012371d523fb3b95bcedfad28 assets/createnuclear/models/item/blue_anti_radiation_leggings.json -3a5955f81eeed80e907bf8e2ee4df14fe42843f0 assets/createnuclear/models/item/blue_cloth.json -2e364d92951412b2dd7d9fbb0209fc8f3194bcd5 assets/createnuclear/models/item/brown_anti_radiation_chestplate.json -d61337a67071319320d75383a62ecac11c3222d1 assets/createnuclear/models/item/brown_anti_radiation_helmet.json -ce17b82389ca226bc9e55072ae0dab1ef049e96f assets/createnuclear/models/item/brown_anti_radiation_leggings.json -8cdcca32a87171e2c709e762165330b2f0389f90 assets/createnuclear/models/item/brown_cloth.json -63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/createnuclear/models/item/cat_irradiated_spawn_egg.json -63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/createnuclear/models/item/chicken_irradiated_spawn_egg.json -047d097f30f9586494547715d07271c6994acd18 assets/createnuclear/models/item/coal_dust.json -0c682ff48601bf7f42c8561819ecede780664fbf assets/createnuclear/models/item/cut_autunite.json -11220bd60ab51e05a978a8322511c224d15bf886 assets/createnuclear/models/item/cut_autunite_bricks.json -d43ffb4c5491fcd8c98451649c3f4ceb271e8875 assets/createnuclear/models/item/cut_autunite_brick_slab.json -dfea56e99288e64e5061c621e860fa314fc31e9d assets/createnuclear/models/item/cut_autunite_brick_stairs.json -95e992c1e1c881d0f00a234a5e6906b1a5dbf149 assets/createnuclear/models/item/cut_autunite_brick_wall.json -5027aa166900571aa2e4f50ad53869b595ff3426 assets/createnuclear/models/item/cut_autunite_slab.json -bd832947d219746d3264422bc4c82f6acdc5cc3e assets/createnuclear/models/item/cut_autunite_stairs.json -4c0b115eb2a2f8d6e74c612fa6e1aa5b357e9185 assets/createnuclear/models/item/cut_autunite_wall.json -3aa34b484b1eb135c9e2fcd3db675aa8d7927951 assets/createnuclear/models/item/cyan_anti_radiation_chestplate.json -4925fd5469c909ae1e212cb0279f534656ee93a4 assets/createnuclear/models/item/cyan_anti_radiation_helmet.json -84b9d23fadc9fd0a2e45fc3609f6bf16ecb1545d assets/createnuclear/models/item/cyan_anti_radiation_leggings.json -de649e8356e85e802df3e64df8fd663ce62ba16d assets/createnuclear/models/item/cyan_cloth.json -34c28d31d8b93699cc6ffab724d9c51670c0f3e2 assets/createnuclear/models/item/deepslate_lead_ore.json -1f160865067749c0bed163a84a61581631294141 assets/createnuclear/models/item/deepslate_uranium_ore.json -5a2694d92c4708ca23ddfa67666ea26be66b9a45 assets/createnuclear/models/item/enriched_soul_soil.json -306f5731ab788fa3cf3d75a7edfcc68b9c20613a assets/createnuclear/models/item/enriched_yellowcake.json -a3b71025626527be742999a0256e9c2290c9d42e assets/createnuclear/models/item/enriching_campfire.json -78240d0c081d144592e76af622d0c9929569db17 assets/createnuclear/models/item/graphene.json -3c0e762c21fa4fa5724f5570c190e89d247ee71b assets/createnuclear/models/item/graphite_rod.json -eae1421ac37a98d0fc795bab8f349906aed521dd assets/createnuclear/models/item/gray_anti_radiation_chestplate.json -c88d66c0a041c51ee8089e5596169dc6c353fb13 assets/createnuclear/models/item/gray_anti_radiation_helmet.json -e66dc779ab853aecc35e6ccfba5d9dba78cd0574 assets/createnuclear/models/item/gray_anti_radiation_leggings.json -75bd474d73be3c041ceb82627cc438b2775e9b1b assets/createnuclear/models/item/gray_cloth.json -b4ddee28d16f837d70e311c84748b18fe3cdc21a assets/createnuclear/models/item/green_anti_radiation_chestplate.json -d0f9a216114a583e097ef8369c4ed74f50270672 assets/createnuclear/models/item/green_anti_radiation_helmet.json -00308a5c640b2ec21ad96b313789a2ec28cff516 assets/createnuclear/models/item/green_anti_radiation_leggings.json -104ab85c7f23d9239608603e6cb2227bc60b585f assets/createnuclear/models/item/green_cloth.json -ad33dca8ecf90a8bc1ebb61c2007af72c427e9ed assets/createnuclear/models/item/layered_autunite.json -17ec52f71bd19239771c599ee80d9ffa073738af assets/createnuclear/models/item/lead_block.json -649fce08e620f39f776ab8ae8dcb17e0fd77c82f assets/createnuclear/models/item/lead_ingot.json -4d18b6f86e9ebcff28c08b9876f1819a067cd290 assets/createnuclear/models/item/lead_nugget.json -3fc1094857b79873a966d6de2dc9ec3b711caadf assets/createnuclear/models/item/lead_ore.json -af0ce4256f68076af5c6a6da9faa98919eeb0a1c assets/createnuclear/models/item/light_blue_anti_radiation_chestplate.json -71bbf3a4c34d499581bc7d0bb8fee63d2441c903 assets/createnuclear/models/item/light_blue_anti_radiation_helmet.json -e3acc02d9c87edea70fb57e88e172209b2b17a3f assets/createnuclear/models/item/light_blue_anti_radiation_leggings.json -f3b5417e33bf6c166d8cffbf16ab0f9893e29c6d assets/createnuclear/models/item/light_blue_cloth.json -4904ab86720357735b330a1a70d303d2218c31f6 assets/createnuclear/models/item/light_gray_anti_radiation_chestplate.json -8ed063e9486b9d6d830bba43a35a3b5dd07ea0a0 assets/createnuclear/models/item/light_gray_anti_radiation_helmet.json -114178d84e51715bc7e81cec53fca931499f72e4 assets/createnuclear/models/item/light_gray_anti_radiation_leggings.json -33bd84e37cc034cdd6d6516af77f944b7399f3fa assets/createnuclear/models/item/light_gray_cloth.json -c982468ef610a204620f31cf7bc9b19b4163489c assets/createnuclear/models/item/lime_anti_radiation_chestplate.json -50c312969d1f3f0c5fad27639ba3f95d0853cb14 assets/createnuclear/models/item/lime_anti_radiation_helmet.json -cb27df2e5ed459128cc7d83786c9f32d91242e56 assets/createnuclear/models/item/lime_anti_radiation_leggings.json -b20e1b4dd0745ead1aa2248a91df5dde465e0938 assets/createnuclear/models/item/lime_cloth.json -5ad910a7a4ee066d98d1727988557725038f957e assets/createnuclear/models/item/magenta_anti_radiation_chestplate.json -e02c005625f9ab199ba04201152973e016b16831 assets/createnuclear/models/item/magenta_anti_radiation_helmet.json -5e91eecf2e5def0f863b5d7d9b3625a62e4de7af assets/createnuclear/models/item/magenta_anti_radiation_leggings.json -4799138766c26496b41807407a4b1ce2106cf7b7 assets/createnuclear/models/item/magenta_cloth.json -626c65938b0109839ff3f48fecabe659fe38a657 assets/createnuclear/models/item/orange_anti_radiation_chestplate.json -72af25b71ba1417c58137fce1070c09cc65a61b5 assets/createnuclear/models/item/orange_anti_radiation_helmet.json -af14c1a038ff14285b1d78dfbcab0a8e44df14e5 assets/createnuclear/models/item/orange_anti_radiation_leggings.json -cfc8b9126dc3fe3b993c5e6201533aecc07989c3 assets/createnuclear/models/item/orange_cloth.json -45223d8e65c235302e923cda583fff09cb4ab156 assets/createnuclear/models/item/pink_anti_radiation_chestplate.json -0703dcb90ab1cbe58167c0872bd9e9950de99531 assets/createnuclear/models/item/pink_anti_radiation_helmet.json -af0dd245292fd2952c37e2d81bfff0a34f8aa5f6 assets/createnuclear/models/item/pink_anti_radiation_leggings.json -9f81dccbba864441a1d76a5312216faa44e6e44b assets/createnuclear/models/item/pink_cloth.json -6d3410aa77b41ada9809f246f1d1a1a982449736 assets/createnuclear/models/item/polished_cut_autunite.json -6919e7571fa3bd76fa08b0a707f1f9367e203a49 assets/createnuclear/models/item/polished_cut_autunite_slab.json -d3459552745c002eb95585853ddec7b638b4c11f assets/createnuclear/models/item/polished_cut_autunite_stairs.json -b6c3a22d368bd0796b004ac27b8e453a16e7d14c assets/createnuclear/models/item/polished_cut_autunite_wall.json -86d99549567048667239096badcb4249d6dddf2b assets/createnuclear/models/item/purple_anti_radiation_chestplate.json -9e3c06e53c3bb29bd4fca943a6700e97e81a6705 assets/createnuclear/models/item/purple_anti_radiation_helmet.json -047c75651f6c6d8888fcfb1416e67dcb91f3dd99 assets/createnuclear/models/item/purple_anti_radiation_leggings.json -3171211192a2b92005177fd1ee2ce7fbe2592b52 assets/createnuclear/models/item/purple_cloth.json -7da7ddaac39353657166badddc16fe9eb79f1a27 assets/createnuclear/models/item/raw_lead.json -ba58a4c086d8937d6703795a9d80435c2d450e35 assets/createnuclear/models/item/raw_lead_block.json -2e30d8c1f56b02bd000509c2a6b32f4ff6c33290 assets/createnuclear/models/item/raw_uranium.json -5bad8990f31085232b63b11d295b90b581af9a82 assets/createnuclear/models/item/raw_uranium_block.json -ef76b3a3a97b5d1901d7e8ac17009381de418ab8 assets/createnuclear/models/item/reactor_blueprint_item.json -ee9b06de6d4e5f722543a83e5d9f7564ac6d7f70 assets/createnuclear/models/item/reactor_casing.json -7d0b9c3d7301e1f419441b69f152955fc69c5633 assets/createnuclear/models/item/reactor_controller.json -118e595a42c557d4eb97750ba31699a0e3f29ed8 assets/createnuclear/models/item/reactor_cooler.json -7e444d9dc776530d017fc28fe18dad0fabeedcdc assets/createnuclear/models/item/reactor_core.json -6726831326d47e5e416216e0ec1d3fd214110e89 assets/createnuclear/models/item/reactor_frame.json -18dc2031fd8aeba588d92e43093fb76e78b2bbe4 assets/createnuclear/models/item/reactor_input.json -69e464d730b826a0c28ed3cfeab28c4c561ec1b0 assets/createnuclear/models/item/reactor_output.json -a108ac857c776255abc1631429c5ffabb3e2a8de assets/createnuclear/models/item/red_anti_radiation_chestplate.json -b7a56e4ac63519df8fcefb9b18a2583991bd9f34 assets/createnuclear/models/item/red_anti_radiation_helmet.json -54aa0a32f1eeedc5b78eb223ea01c3ff30ae365d assets/createnuclear/models/item/red_anti_radiation_leggings.json -4db93da70d6a7549155201b7d9d68355449652ac assets/createnuclear/models/item/red_cloth.json -78a9e80073512a111cb936a516d290a824846ff2 assets/createnuclear/models/item/reinforced_glass.json -9b008029869830da5e8b8b2701e80a3a50945382 assets/createnuclear/models/item/small_autunite_bricks.json -9b83b53d90891eaf7aa4693eafe2876a831e0be2 assets/createnuclear/models/item/small_autunite_brick_slab.json -3e80ef1d80473c73a723d3c4b5c1409c7998d70f assets/createnuclear/models/item/small_autunite_brick_stairs.json -9286e69b3a5215a17ccb178933c2f52a9adb847f assets/createnuclear/models/item/small_autunite_brick_wall.json -7f33b090f2821bdeb07b2938b1618ad3f309248f assets/createnuclear/models/item/steel_block.json -bcb30dce2419ce1ec2e043eaff83df82ac8a4bec assets/createnuclear/models/item/steel_ingot.json -4b0492cf73c071f13538ce485419e46a164c99c7 assets/createnuclear/models/item/steel_nugget.json -2b6958059c3a4c8aee7fb4c003feba12dd0ab252 assets/createnuclear/models/item/uranium_bucket.json -7b15a9300d0f6d106e589db3dcd3294781d0bdca assets/createnuclear/models/item/uranium_ore.json -3b03793c0f5786f258c593e0b140cd6bd10c3b7b assets/createnuclear/models/item/uranium_powder.json -ea04609e8b5c12a7805b1c564bca07fefd6d38ba assets/createnuclear/models/item/uranium_rod.json -798287f6d78ee3d736022963d35a700f42cbdca9 assets/createnuclear/models/item/white_anti_radiation_chestplate.json -7960569836d3b7f0c50ff9a000253098f776a8f0 assets/createnuclear/models/item/white_anti_radiation_helmet.json -31283971103bb25159e8b049b63dfbc408e87d23 assets/createnuclear/models/item/white_anti_radiation_leggings.json -4d85657105612ca5525a14791c3e07cf6bd239b8 assets/createnuclear/models/item/white_cloth.json -63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/createnuclear/models/item/wolf_irradiated_spawn_egg.json -8bdc2fabbfc9fcc7c2ad4a3273897659d90b95ab assets/createnuclear/models/item/yellowcake.json -609c04d42448ccc99291c723c8b6741e870b46d4 assets/createnuclear/models/item/yellow_anti_radiation_chestplate.json -953491d658ba39add0f080137ebfafc9ac07ee1d assets/createnuclear/models/item/yellow_anti_radiation_helmet.json -b20aeafcdcd235c7d89067d5331b823535b82522 assets/createnuclear/models/item/yellow_anti_radiation_leggings.json -a1970879fd57836f5ae5d23352cdca277095bc7d assets/createnuclear/models/item/yellow_cloth.json -645c75625b389cc20363a60611842f63607dde6e data/createnuclear/advancement/recipes/building_blocks/autunite_from_stone_types_autunite_stonecutting.json -1ae444421205a2d61dadcca5cd4e2aff2997e720 data/createnuclear/advancement/recipes/building_blocks/autunite_pillar_from_stone_types_autunite_stonecutting.json -e349dda5e6ac121e22d4d93047f6da33db800b8f data/createnuclear/advancement/recipes/building_blocks/crafting/enriched_soul_soil.json -037502ba979c33bdf471f663846d446cf2c9a58d data/createnuclear/advancement/recipes/building_blocks/cut_autunite_bricks_from_stone_types_autunite_stonecutting.json -36c67a42fc9886dc7f8e3910c5da40243a0c96f1 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_slab.json -90b74a9ba34490ca3d4430a28330073bf4fdc2f6 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_slab_from_stone_types_autunite_stonecutting.json -9f93a2cdaee9acc10311d3c142e082935fa85ee6 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_slab_recycling.json -364f82f401ad323773e5645d1f20b7a6f36a028b data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_stairs.json -2d34a755bd84f74d9d87915157807b77b7d5a8e9 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_stairs_from_stone_types_autunite_stonecutting.json -746e2c38389ca0f91a1048fd1d42b65119bd930e data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_wall.json -d0078f0b6875c825181e857b16237beeccff688f data/createnuclear/advancement/recipes/building_blocks/cut_autunite_brick_wall_from_stone_types_autunite_stonecutting.json -16d960287fc2033e78d6e7d7699a8fd368898b4e data/createnuclear/advancement/recipes/building_blocks/cut_autunite_from_stone_types_autunite_stonecutting.json -e4e980ce0207906bc770ebb080c01866ed68e032 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_slab.json -3681991c4b555543fb446ddfa5ab5608b3b396cf data/createnuclear/advancement/recipes/building_blocks/cut_autunite_slab_from_stone_types_autunite_stonecutting.json -caa5f9d70ae3c1fc19a453f30766c22b864e86a0 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_slab_recycling.json -fedda494df40e67506ab872ccb448ead5d2c408f data/createnuclear/advancement/recipes/building_blocks/cut_autunite_stairs.json -ce6ea9594dca48d5ac47447ffa2ed32238adc63b data/createnuclear/advancement/recipes/building_blocks/cut_autunite_stairs_from_stone_types_autunite_stonecutting.json -ffc86704c803a402b99c7524eebf221f941ea903 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_wall.json -a50c37e0fde99c662c01aece38a16f6d432b3fc3 data/createnuclear/advancement/recipes/building_blocks/cut_autunite_wall_from_stone_types_autunite_stonecutting.json -9b542ab150da37484c151ffe3d1b6ecfeb8d0593 data/createnuclear/advancement/recipes/building_blocks/layered_autunite_from_stone_types_autunite_stonecutting.json -34b2cae240fe809ec193dae7601c6f1e381d231e data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_from_stone_types_autunite_stonecutting.json -a79a99b5a7642090b8939aed9497c97ad12e747c data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_slab.json -9091f87d4e33d96179bc40faae416784c6cb8f3a data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_slab_from_stone_types_autunite_stonecutting.json -943f287534bfe5fa90de7cbf05e739ee4899a2b1 data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_slab_recycling.json -1eb435da50adb51433602ea62b9dce553578eefa data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_stairs.json -38727bd7f13b818319fbc8e0c32fdb901b9ffa66 data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_stairs_from_stone_types_autunite_stonecutting.json -9d9992c5487d49b264b33817d5fe68ff0998b181 data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_wall.json -55501543e83ef0225ab9a1a43a183aab2df6c420 data/createnuclear/advancement/recipes/building_blocks/polished_cut_autunite_wall_from_stone_types_autunite_stonecutting.json -6b1160d1d99257088be280cf3e75a047f35e9ed4 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/black_cloth.json -c1af7f50475be51573c5f57572eec3831073a33b data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/blue_cloth.json -f851e8f840dd9ab4cc8c442b1ec9344b1d949035 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/brown_cloth.json -e784b004df0fff75d820ac59824df36bb27fe9fc data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/cyan_cloth.json -2181ebade82d021b45ca3d08a7ed1713f7fcf2bf data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/gray_cloth.json -b68975a8a0be3b7c75f910d9d978cf651fd83bd0 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/green_cloth.json -95e6f7eea3e340c38fc546030302bfd4d79f57db data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/light_blue_cloth.json -53be998206aaff4861854fea5eec3eb131b03839 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/light_gray_cloth.json -6ae4b584a79916d3a81a9715b0d663821c0c07be data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/lime_cloth.json -6544069252fc84b7ca861b14832bb3351814241e data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/magenta_cloth.json -dfc2c0aed429fd92da9b298daceb67cb8813471d data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/orange_cloth.json -35b8eb5ec8cc5533a512fb983bb161100c935164 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/pink_cloth.json -fba08995866829ec0b153b70dc0f518e49669615 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/purple_cloth.json -711f401d07ffdecd8de2d72a5e2da00ee670de96 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/red_cloth.json -0d947734920dd508d31d0d7659c9cd28792e8e0b data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/white_cloth.json -3b24b8957595f9b81a8bb1e034c3b25600a91ce9 data/createnuclear/advancement/recipes/building_blocks/shapeless/cloth/yellow_cloth.json -0d4f3a7e8201cb4e0aa9a435915e2313d41c7c19 data/createnuclear/advancement/recipes/building_blocks/small_autunite_bricks_from_stone_types_autunite_stonecutting.json -21ad933339a96f7fb9d35b7af8de57561c9281f1 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_slab.json -8c807c1a3889df15eb039e58df1f7caf23ae1836 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_slab_from_stone_types_autunite_stonecutting.json -8f935c994f8f9656e6699ae995c291cd9fb151c8 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_slab_recycling.json -996932cb30445dd58d79ee0b7458f4640bb96410 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_stairs.json -b591593e24bff98eb83959477db5210389bcff9a data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_stairs_from_stone_types_autunite_stonecutting.json -8a6b40917cfdac102799afb3ecd78f912484aae0 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_wall.json -5ea4ec30969485b3f744eb80b935abc48a9369c4 data/createnuclear/advancement/recipes/building_blocks/small_autunite_brick_wall_from_stone_types_autunite_stonecutting.json -eb45a936e9a453a0bd916c7dad4e2a2e8e3d4039 data/createnuclear/advancement/recipes/combat/crafting/items/armors/anti_radiation_boots.json -15974dc94982bc86c81ed5658220ea5c2cc5e76f data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_chestplate.json -d9bae647e6ebc025011bb065ac70b7c8296f4901 data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_helmet.json -2fc361864d959886d750c641510d17e35dd922dd data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_leggings.json -03b7f1e871d030c124a2eba9bb580ab62c16eb80 data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_chestplate.json -40bd9c2c107d9bf8b37a651e64f67094e213b805 data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_helmet.json -25e4b96a64d97db3e8a6842ebb9edb6eb8091a51 data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_leggings.json -3bec2bf79f88a1265e958c747ec965107124ade1 data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_chestplate.json -765095412827d711345b0429ceb32fc0322d7417 data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_helmet.json -b59fd7932ce90d92cf743cc9bc96f85f0efca0b3 data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_leggings.json -4ba804048c0f42ca02141e7de9936ff0fddb9996 data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_chestplate.json -da8641b0dc4e1f09936c957d2bbf896c5fc8636d data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_helmet.json -d3949d04953ede7c274a94753fcdac461abd08cf data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_leggings.json -468ae9789b567b95ab75376edacd8c38171f3121 data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_chestplate.json -abb580be743604bd893ba7e04fcc2f86fbd88bcb data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_helmet.json -8d6cbbeba02f0e474a3d41fc41f40d4e20be54ec data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_leggings.json -af43192b0dbac3b1663f849a758d7761e611c3d1 data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_chestplate.json -ec5a63149b95544e38e56228d2a402bd15189835 data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_helmet.json -972a97156f922b1e152133009f85f1e12551234e data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_leggings.json -ac1475f6749dbd4c38f4995a800c0f69944059f6 data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_chestplate.json -5cf64a82b27d2418ed92937535cdd99b175d7e12 data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_helmet.json -26875f42d3b08c3c461900e25be11a30a468195f data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_leggings.json -065e02467f8c1a437cc33e8516ac87e615326aa9 data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_chestplate.json -d2722883201394a33792e5ed7316765d6ca3261d data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_helmet.json -04c2aa666ea51e8d9c2f4086470a54c03f9b0195 data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_leggings.json -cc15b0290ceb9e93126a9aef3107ab457696074e data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_chestplate.json -7e2be3d47d2c4155313bb23752303d331c80675d data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_helmet.json -8a687f0cd3b94febd1e3c2fd8a2cee35e43e1e03 data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_leggings.json -f0a4fcdd54bb31bb6d0712c23b730b11e65da36f data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_chestplate.json -755caee9ed68ee3089d5f88af7c165d8ec08732c data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_helmet.json -725f8963621d94119014438f602d5bfc95244c6f data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_leggings.json -9f4271c09c336fb2bfe0b05274425de4cff04b67 data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_chestplate.json -7982760d668ab13ce5d82d402808f22b3fe1897b data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_helmet.json -2a70a87a9144aced9824ab88fcd3cd4661c1c5db data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_leggings.json -2de3d1a8b5a75249c9939588d9d47825fa8884f7 data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_chestplate.json -b8284a657102158c3186a17be44daac87378f2cc data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_helmet.json -c582436118c1696d783068868cf45a0626d6ab7f data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_leggings.json -a99055d31231bf1ce2e22f07fe68f5c88f07c60e data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_chestplate.json -6f621d0bf9a4d22abdb088de08dbf0aa3ebdbe16 data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_helmet.json -827f59eb4d349366248943c36451cf8d94297823 data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_leggings.json -10329098214c9068d9a1fa87e40d39a67d89a788 data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_chestplate.json -79f7d0c33f4fec80845d2cf1fba05cd5f8a1dbfc data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_helmet.json -d1c12c93b0978f393e0f0c3528cc2834f7510613 data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_leggings.json -cb37a059540dd0ba0054682956ed134d7a713a89 data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_chestplate.json -1a77403790aec78528c98f7ecb807f9f72f4f2cc data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_helmet.json -e72ec9a43977fd1d4bf884ad89fde59351da6b50 data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_leggings.json -42a45cc6b53cc39ca61639e972c2382337256764 data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_chestplate.json -c5db2fc910cb394f894fe2a6d8b46288c1af8a62 data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_helmet.json -ffb2ad68967edda9818cbeb5d73de961aec2e915 data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_leggings.json -aa149d3676247b682c6d2e8e02e87f55f8cc3a2f data/createnuclear/advancement/recipes/decorations/crafting/raw_lead_block.json -1f43a98395758f3159e69298327b6546f6576ae8 data/createnuclear/advancement/recipes/decorations/crafting/raw_uranium_block.json -e9881aa1d6af63ece64dbe5a9a7d412de3840c20 data/createnuclear/advancement/recipes/decorations/crafting/reactor/reinforced_glass.json -a1b0ce29f7b72108255deaf87bde4e4cdb878e7b data/createnuclear/advancement/recipes/misc/crafting/enriching_campfire.json -4f06a9916362a31e032d558004c7daca76d50a4e data/createnuclear/advancement/recipes/misc/crafting/lead_ingot_from_decompacting.json -7942dbc0681d08d4eb45fd8c7efe439f45e8749b data/createnuclear/advancement/recipes/misc/crafting/lead_nugget_from_decompacting.json -58995ff78a4223f9aff3f40e055773e704ffa67a data/createnuclear/advancement/recipes/misc/crafting/raw_lead_from_decompacting.json -01f9b9dd8545687992a425693e25923db093cc7f data/createnuclear/advancement/recipes/misc/crafting/raw_uranium_from_decompacting.json -8b9d3beac96fa049754d6792a18d46fae4e16510 data/createnuclear/advancement/recipes/misc/crafting/reactor_blueprint_item.json -608ba81e528f6e9bdb5e8ab007dcc743397a33f9 data/createnuclear/advancement/recipes/misc/crafting/steel_ingot_from_decompacting.json -92f6a4abe3553b8c5958650d750f65907963015b data/createnuclear/advancement/recipes/misc/crafting/steel_nugget_from_decompacting.json -e13e61b6ef24889f1d3d7948892b3e9e3799aa4f data/createnuclear/advancement/recipes/misc/shapeless/reactor_blueprint_item_clear.json -a021646becb7b6411eddd86644e5b17c8365582c data/createnuclear/loot_table/blocks/autunite.json -62b7087350b0a9af9007b848c7f619a730e90693 data/createnuclear/loot_table/blocks/autunite_pillar.json -771b416236bcc21f380e0f312c61803224987616 data/createnuclear/loot_table/blocks/cut_autunite.json -3b81b5b58b7ef985348cf511e609064a7171d7dc data/createnuclear/loot_table/blocks/cut_autunite_bricks.json -feae7c8978bcce63f2eeb2ad6ed6a7ef53cbc13e data/createnuclear/loot_table/blocks/cut_autunite_brick_slab.json -1fa4418198a079b6236b2f3e4b11a7f7d0fc6962 data/createnuclear/loot_table/blocks/cut_autunite_brick_stairs.json -db666ffaca36edc9e246e225f225c1e87604dd88 data/createnuclear/loot_table/blocks/cut_autunite_brick_wall.json -10aff7424eefd85e50269c66e60ae343043193cd data/createnuclear/loot_table/blocks/cut_autunite_slab.json -e6e624e978fdacfa3cdd123d23d021f504308149 data/createnuclear/loot_table/blocks/cut_autunite_stairs.json -f28efa9fb383b86c770b8c7344fc30f6ab9200d3 data/createnuclear/loot_table/blocks/cut_autunite_wall.json -85378419ab3a9306dc242c7e5bc6b7edb557f055 data/createnuclear/loot_table/blocks/deepslate_lead_ore.json -a6fb15f04e26a6f99d0faef6472872cf1a89e838 data/createnuclear/loot_table/blocks/deepslate_uranium_ore.json -76ca23065681dfd7f18dbbc5a65b8ab8bc40c20c data/createnuclear/loot_table/blocks/enriched_soul_soil.json -24bab1e399200ead33320c32ce8b33d4182c1ccc data/createnuclear/loot_table/blocks/enriching_campfire.json -aa8efeb48b11261953f7d90e6d7db38411550694 data/createnuclear/loot_table/blocks/enriching_fire.json -297b7824fc2eea67ef47760da549f73e93424b60 data/createnuclear/loot_table/blocks/layered_autunite.json -efe2ad634ad8b801a8fa69f45516b30157b46771 data/createnuclear/loot_table/blocks/lead_block.json -05a8fd97474d3af10a805658b6025503beebf2f5 data/createnuclear/loot_table/blocks/lead_ore.json -7ad41810138d7b55a5d9d0db0956cd255e879632 data/createnuclear/loot_table/blocks/polished_cut_autunite.json -d5fb5ebfe991980abfd6f1932575363d026d8859 data/createnuclear/loot_table/blocks/polished_cut_autunite_slab.json -8205832fc48bd24351b4b433f92a70a533336f48 data/createnuclear/loot_table/blocks/polished_cut_autunite_stairs.json -2c3ca9fb7683d1edfdc2e4fcd4b25ab7f40c3ab6 data/createnuclear/loot_table/blocks/polished_cut_autunite_wall.json -66ab1033aebea1383fe3f09c7468f4cd60d8aa25 data/createnuclear/loot_table/blocks/raw_lead_block.json -0998d5a55f2dc10e85e83dd74bd91d4a3913f61f data/createnuclear/loot_table/blocks/raw_uranium_block.json -af059cd55441441329347fbd569245b539b095db data/createnuclear/loot_table/blocks/reactor_casing.json -e76c0b96c978e266f39eca8e46cd5ba2388e1749 data/createnuclear/loot_table/blocks/reactor_controller.json -95a90d9d9a553448c878dfdf4b153ceada923030 data/createnuclear/loot_table/blocks/reactor_cooler.json -daa4fad27f07fd72cb25a524464edea9efe771b7 data/createnuclear/loot_table/blocks/reactor_core.json -576b0bf970ddbdd11ec06963e1d65e08e63d69e1 data/createnuclear/loot_table/blocks/reactor_frame.json -be48e04b069441c8593aab5e9bf78f4edc2dd249 data/createnuclear/loot_table/blocks/reactor_input.json -37af2b0b5eacf53995703344a45fb3f4d0efe1f9 data/createnuclear/loot_table/blocks/reactor_output.json -03f05a92cf4e1565fe3482f763a1be9e9dd7f088 data/createnuclear/loot_table/blocks/reinforced_glass.json -48c0d8d35932fe1cdb00e5055caa6c1969a8e4cd data/createnuclear/loot_table/blocks/small_autunite_bricks.json -d51f9b307f2986ac086d32f48bd41e6dc4024348 data/createnuclear/loot_table/blocks/small_autunite_brick_slab.json -4014ab450bb5de0522690577486f2fbbc334de9c data/createnuclear/loot_table/blocks/small_autunite_brick_stairs.json -8718c7e7cce27e299611ee34792cdb59f3434e39 data/createnuclear/loot_table/blocks/small_autunite_brick_wall.json -94dc8e72195da5aa505c6d5a3785ccfea30f7c05 data/createnuclear/loot_table/blocks/steel_block.json -d6135780d6ae9e0c890f6ccf6932250faeea5372 data/createnuclear/loot_table/blocks/uranium_ore.json -fba1a7bdb0835c034aa5ef52ebf589123d41b33e data/createnuclear/loot_table/entities/irradiated_cat.json -2d8f5d7d7babd2b02ae836846e62daabf84de427 data/createnuclear/loot_table/entities/irradiated_chicken.json -f91f43a39c80f583f878ea1a0d944798c05f2388 data/createnuclear/loot_table/entities/irradiated_wolf.json -ef428465f5d04edfb67c7357bef7936e93800cb0 data/createnuclear/recipe/autunite_from_stone_types_autunite_stonecutting.json -5988520980fc9ae12384874425e01110816ea779 data/createnuclear/recipe/autunite_pillar_from_stone_types_autunite_stonecutting.json -b5fb128b53c749c043861fee9db236aa5ac0e4f5 data/createnuclear/recipe/crafting/enriched_soul_soil.json -cd7d5f4394cd52bc35e4e086c7a2ef658416d9bf data/createnuclear/recipe/crafting/enriching_campfire.json -e8028bc85c676927033ae811ad9f52a16697e96d data/createnuclear/recipe/crafting/items/armors/anti_radiation_boots.json -dc085763e36da153d74c0ea79833b4dfdb8431eb data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_chestplate.json -e45fc4f0067c21755a31debbbda3a5ef8be144e8 data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_helmet.json -43122e2a7bd237f5bed847ebc86263cd915ee858 data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_leggings.json -5f01e478e7d85fa6b8f4a6ae700ea482ff5573c3 data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_chestplate.json -f82785c9ba2814d928f7200092c3e9b363903d41 data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_helmet.json -ba24d945cc1a845df34f925767de53a954748ecc data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_leggings.json -c78ea327795125fd7e1e978c59b392fc253f7ed1 data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_chestplate.json -e6158a97df846d7d74a34cfdb9e9628e3a7ce2db data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_helmet.json -f052804b12994a53f87bdd3232c04d16ec4a2f15 data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_leggings.json -13332056a7f6d06098a7a3f259aa99c69f5afcb8 data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_chestplate.json -43a3a61ca2ce11658f5b64184409a3dfb8da1403 data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_helmet.json -a7a52ecb6e7869c604e4479a583c86bc2f223f96 data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_leggings.json -70c0c9ea9635ce27e45ddbad2b99c9f2e2ce4719 data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_chestplate.json -f6beee15053fd44f8fa99a0895930c4ced9b31d5 data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_helmet.json -c6efa9608303f91e96b6a976657a0b02a3f932c1 data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_leggings.json -4ef403baf8ac823c646551d138cdae013bc4ab2b data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_chestplate.json -b507168a0933458d626ff4de1c03b228fa2f02ad data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_helmet.json -494df5da6712e7a7ad77743f81b8c13c51b4133e data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_leggings.json -935cfede121335cf255c04443a14c4be0a165613 data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_chestplate.json -ec619b2f1fe4a20d4a7bd79d2a718fdaac8fa546 data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_helmet.json -882f1e13a7adf293c3fcaed2c9b1ff7e53e0a3ef data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_leggings.json -6593ebc77d818b839f45a3847edebc81f8fb2aec data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_chestplate.json -7ea88dcc18b76e2673811254f8a5b7e50bf1f812 data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_helmet.json -86b76987f7e928563e823def2ade6fe6b46a8de6 data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_leggings.json -b3c16d4ea8e8c41597690029ac4da6ca812baf27 data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_chestplate.json -9396b0cbe9042156852d6f824967161e073e28c6 data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_helmet.json -148c2f0f1781edc2a586b5bde15b1ace179e7495 data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_leggings.json -430b5953e9a1a799d96eb0bd3e58b6330130c160 data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_chestplate.json -de90ec41a274369b3a037ee642efc1ea3f99d7f8 data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_helmet.json -83261868049adc05332e99c4612d756a41d25a8f data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_leggings.json -c336fc325fe817defc512fab4aeeae47b2201576 data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_chestplate.json -85dd76ada72ca4fa2037fa9969a4b1ac40b20648 data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_helmet.json -463f9ae40535e0e80389d4ece8a186d044fd95b0 data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_leggings.json -c4290b55e92aead61280a94cb93794555e55f670 data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_chestplate.json -d2ac5f15270d3224eebc36ca3b0c4836b99e588f data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_helmet.json -1ecb4ba13dd2ec7babc61a9d57f16257f27d032f data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_leggings.json -08088ad8866eb5dbdc64d30597c90c83b01f44db data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_chestplate.json -c81cc2d5b26b60d0533e59e6dfeec874da658c28 data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_helmet.json -cf840a2cbc641705cd8738f5673885263143fa2e data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_leggings.json -0eb06ea2faee0e187a1065bde29ada611574f925 data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_chestplate.json -ea817f9b9db7c491ad588c42ffb0a2eeec6a0adb data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_helmet.json -5fbd49b322203919f5fc11db034cdf331bb08421 data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_leggings.json -f8bfdc04eece24bfd4d059ad85a8cf04fe671775 data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_chestplate.json -b3fc28cc8c00f23066461ca3eba3d9879a65ada9 data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_helmet.json -2056d569e4b341b81dda973db35d86cb5fc66e30 data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_leggings.json -f1d40e4e825e4ab15e0ff95bd8c8bc04a8e16c49 data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_chestplate.json -fe64ee6856cc9798a1f0f18e97c22241067e1fe6 data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_helmet.json -8e5aa3bccec84f50ad317260690567e2cc6a33e0 data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_leggings.json -ac1aafbe0f6261f8cf77462fdc7e6ebbffac5431 data/createnuclear/recipe/crafting/lead_ingot_from_decompacting.json -fd535efce0c108d879e5a1f13aface5586fc3127 data/createnuclear/recipe/crafting/lead_nugget_from_decompacting.json -4ecbbca33f6971b904c365a41d67d1f610ca368d data/createnuclear/recipe/crafting/raw_lead_block.json -c9dce33293c71961aea5c4ca04ca837449b87ac7 data/createnuclear/recipe/crafting/raw_lead_from_decompacting.json -a8368b7ba6ad28c6073653978c11a17b8e61c009 data/createnuclear/recipe/crafting/raw_uranium_block.json -9a0f17a6a4970542ecf42b775fdcea11f0617c74 data/createnuclear/recipe/crafting/raw_uranium_from_decompacting.json -ed745f567cc3683a58121f3d617ed9d0971a7681 data/createnuclear/recipe/crafting/reactor/reinforced_glass.json -57ce2170813201b6a6c6de35ca8e901c8563894d data/createnuclear/recipe/crafting/reactor_blueprint_item.json -000385de7b8a84be8a42ecbc2e486e47978593e6 data/createnuclear/recipe/crafting/steel_ingot_from_decompacting.json -6f664e863b1a0333d16c20d3aacddd54e6f785fb data/createnuclear/recipe/crafting/steel_nugget_from_decompacting.json -2224ce14a45b2bee57b4390aa5e962c92f223ba1 data/createnuclear/recipe/cut_autunite_bricks_from_stone_types_autunite_stonecutting.json -e0e6e0e4020ea52282b7251c4a5ce9f38ecdc124 data/createnuclear/recipe/cut_autunite_brick_slab.json -02a7ff87c030a7c830141f3dd89aaf549900cf6a data/createnuclear/recipe/cut_autunite_brick_slab_from_stone_types_autunite_stonecutting.json -06eba624cb6116b29074a3fb77390ef3079d600d data/createnuclear/recipe/cut_autunite_brick_slab_recycling.json -2f4e6952fb1718c482ea4b25c640bb902e4a39a4 data/createnuclear/recipe/cut_autunite_brick_stairs.json -8a2a50e11d952d65dd3eec9aa178a46fa7c34aff data/createnuclear/recipe/cut_autunite_brick_stairs_from_stone_types_autunite_stonecutting.json -ec7330ca42e57fe65afa7adc79f0b197b683c5e9 data/createnuclear/recipe/cut_autunite_brick_wall.json -77611fdf35151dd19a3e8fcfb7412ecee27b0716 data/createnuclear/recipe/cut_autunite_brick_wall_from_stone_types_autunite_stonecutting.json -3dab935cb933f719ae1510a793be63c50ade9695 data/createnuclear/recipe/cut_autunite_from_stone_types_autunite_stonecutting.json -359e02720c227b1777749c56f2aecc1dbb11cb5c data/createnuclear/recipe/cut_autunite_slab.json -2a1715abf4ee80450be9828ccfc5a5b8eba88708 data/createnuclear/recipe/cut_autunite_slab_from_stone_types_autunite_stonecutting.json -94601c8648c2eb3e5b31f8d4f92b9c967daced69 data/createnuclear/recipe/cut_autunite_slab_recycling.json -cdd82b6abc937c26877e60a12c4fa4c067bd33d2 data/createnuclear/recipe/cut_autunite_stairs.json -60806f0889257d1def7927f5c81c657e0db7e832 data/createnuclear/recipe/cut_autunite_stairs_from_stone_types_autunite_stonecutting.json -157d6e133873c667a05529ef0d9d1f954d3302b6 data/createnuclear/recipe/cut_autunite_wall.json -e1c81dea36b60f800b9d15deb9da1d436d9e9933 data/createnuclear/recipe/cut_autunite_wall_from_stone_types_autunite_stonecutting.json -9d8784be2feafcacc745f032877ea39ec54d07ba data/createnuclear/recipe/layered_autunite_from_stone_types_autunite_stonecutting.json -3d8239684e4f6d0810e0cc7d52512bee2047ef7c data/createnuclear/recipe/polished_cut_autunite_from_stone_types_autunite_stonecutting.json -5a724d50573d64c00b83c56596473f3444607bbd data/createnuclear/recipe/polished_cut_autunite_slab.json -324ddb54f95fc52ebe1272496103ca1ca2d6c131 data/createnuclear/recipe/polished_cut_autunite_slab_from_stone_types_autunite_stonecutting.json -0b84fc45f98402f0aa890c477fac697807d70486 data/createnuclear/recipe/polished_cut_autunite_slab_recycling.json -92b3b5d69ac2cdabd0169188a8e738b46ae8f568 data/createnuclear/recipe/polished_cut_autunite_stairs.json -a76add5403acbcdda599a3a3a2d7b974578314a8 data/createnuclear/recipe/polished_cut_autunite_stairs_from_stone_types_autunite_stonecutting.json -660c01c1c4cf5d680308d582431efb5d489924df data/createnuclear/recipe/polished_cut_autunite_wall.json -b00d1cbc32c57359488d671a9194eb0bb2d52bf3 data/createnuclear/recipe/polished_cut_autunite_wall_from_stone_types_autunite_stonecutting.json -e95cf3facd093fb0cf473ac9cd8c43eb784ac87e data/createnuclear/recipe/shapeless/cloth/black_cloth.json -f9b95d15f94209fdff416386550c36a574d24062 data/createnuclear/recipe/shapeless/cloth/blue_cloth.json -91b9dd165ef39f3bd994c3cbc278065dc36f17cf data/createnuclear/recipe/shapeless/cloth/brown_cloth.json -4dd4785bba6def60d86f3a2034a3236a08b418b3 data/createnuclear/recipe/shapeless/cloth/cyan_cloth.json -a6f5e052751fca59e23bf07e90213b843bd497bd data/createnuclear/recipe/shapeless/cloth/gray_cloth.json -8b99effc73ca3780f1bc2a2bfdd949d04345d5f0 data/createnuclear/recipe/shapeless/cloth/green_cloth.json -0feddcc0f23fb66450fb2a74837dd0b93268484d data/createnuclear/recipe/shapeless/cloth/light_blue_cloth.json -dbd05f2a0a1677378a1bd0920a692a941c91900b data/createnuclear/recipe/shapeless/cloth/light_gray_cloth.json -8011429c246463bca2112b895f9e753766ee1165 data/createnuclear/recipe/shapeless/cloth/lime_cloth.json -703e8a15407f6a69f4942312e4c54e609f53d13a data/createnuclear/recipe/shapeless/cloth/magenta_cloth.json -e890e47fe3a573cbb15cf750180423158846fd63 data/createnuclear/recipe/shapeless/cloth/orange_cloth.json -8aa5d46eff53f259ae35faf023b84c274ba7353b data/createnuclear/recipe/shapeless/cloth/pink_cloth.json -3846f8858f9711b561d9f578aa6211dea6676b17 data/createnuclear/recipe/shapeless/cloth/purple_cloth.json -aa5b4721b820b9ac4f8e4f671e5f9eb9b51c6b00 data/createnuclear/recipe/shapeless/cloth/red_cloth.json -b47ebe3c05ebdd3200aa081941a031b2ea22718c data/createnuclear/recipe/shapeless/cloth/white_cloth.json -d756a4fde65a9d9cf8c13a5054d761bc1f3faac0 data/createnuclear/recipe/shapeless/cloth/yellow_cloth.json -3f92b2982573240f019dc370eed41e12ab8963cd data/createnuclear/recipe/shapeless/reactor_blueprint_item_clear.json -43fabb40399e048b2eaeff5f0ea8f2e5d441a8f1 data/createnuclear/recipe/small_autunite_bricks_from_stone_types_autunite_stonecutting.json -4be05821d3cc4ffac867f4bb224d4217aaf45b1d data/createnuclear/recipe/small_autunite_brick_slab.json -da40f5d524c9440d7d1300f543726f77b6fac1e0 data/createnuclear/recipe/small_autunite_brick_slab_from_stone_types_autunite_stonecutting.json -c05dcc6178e1be10c8a8a7f7b9aff7ff47775e16 data/createnuclear/recipe/small_autunite_brick_slab_recycling.json -08e264e297d18de78a3fae40e529043c515e134a data/createnuclear/recipe/small_autunite_brick_stairs.json -e9950d7f4f382bf21c9b3817ccd4123438284694 data/createnuclear/recipe/small_autunite_brick_stairs_from_stone_types_autunite_stonecutting.json -58733c26e138219a3faacab87f5e19277ef99217 data/createnuclear/recipe/small_autunite_brick_wall.json -c094aebdafd05ba86f8accd0e65cf0318771efda data/createnuclear/recipe/small_autunite_brick_wall_from_stone_types_autunite_stonecutting.json -a7d4278d8a39649c8b658ad2f3f1d092cb012bdf data/createnuclear/tags/block/enriching_fire_base_blocks.json -509b5baa813ae0dc3345fd97754e4088132359ec data/createnuclear/tags/block/fan_processing_catalysts/enriched.json -925cb97bc13b3122fe17e59ff3ec2fe4d1eaacd5 data/createnuclear/tags/block/lead_ores.json -bad88bea18fec41c7ad6fa4d396feacc0346a137 data/createnuclear/tags/block/uranium_ores.json -e8b97836e0a934f9023ba18e6ad44e60dca4532d data/createnuclear/tags/entity_type/irradiated_immune.json -35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/createnuclear/tags/fluid/uranium.json -7422c4cd9d6dd716f91311faa1fb7e26aa9ac345 data/createnuclear/tags/item/all_anti_radiation_armors.json -e3fe4325aafb669d287c17b5b30953e4fb709110 data/createnuclear/tags/item/anti_radiation_armor.json -fadb3957b979d82146790ef3550e38606760421e data/createnuclear/tags/item/anti_radiation_boots_dye.json -e7d6ce5456dd6ed6f018a8fb2f3a14b5b4f78e52 data/createnuclear/tags/item/anti_radiation_chestplate_dye.json -0845acff015f78c494df2cd6754c5cff10d77c05 data/createnuclear/tags/item/anti_radiation_chestplate_full_dye.json -3f127db66e68fd3aac662a14e4cbacc4204efa8e data/createnuclear/tags/item/anti_radiation_helmet_dye.json -b5d23f0bc26a4e3a72cde40f3c6d59c03c818b4d data/createnuclear/tags/item/anti_radiation_helmet_full_dye.json -0e3c30cdbfaa4b73bac1276fb973db733b934619 data/createnuclear/tags/item/anti_radiation_leggings_dye.json -bebad856ee0f047735060f28544eb6149d8c2b20 data/createnuclear/tags/item/anti_radiation_leggings_full_dye.json -2e4d08932c4a84863f0198eb2845f80d8fda1221 data/createnuclear/tags/item/cloth.json -8e6598f14a72a61cbe1e5ed2aaea229fb2dd74e6 data/createnuclear/tags/item/cooler.json -c5587bb72c54f59e9f9a4cd2c3e6bedb78ee198d data/createnuclear/tags/item/fuel.json -925cb97bc13b3122fe17e59ff3ec2fe4d1eaacd5 data/createnuclear/tags/item/lead_ores.json -53e435b1776a11737c64eac604fda6cd48acfc4e data/createnuclear/tags/item/stone_types/autunite.json -bad88bea18fec41c7ad6fa4d396feacc0346a137 data/createnuclear/tags/item/uranium_ores.json -d8d6ad7a4fc31fd68a98b368207c359fb610f417 data/create/tags/block/safe_nbt.json -75f0600da4891d0f4a3329fb44cac6c4945a0b49 data/c/tags/block/glass_blocks.json -38aa0fddd24ec7dde10f1e2804328660a2019ac8 data/c/tags/block/ores.json -925cb97bc13b3122fe17e59ff3ec2fe4d1eaacd5 data/c/tags/block/ores/lead.json -bad88bea18fec41c7ad6fa4d396feacc0346a137 data/c/tags/block/ores/uranium.json -dec8291df390fe12bd034da156c39432cccef0d4 data/c/tags/block/ores_in_ground/deepslate.json -f36fa9b8ea20e21fd4a452ea0ec7ce557acd3ac2 data/c/tags/block/ores_in_ground/stone.json -a7258ae3454252e874b324fbd81b880ce52759c4 data/c/tags/block/storage_blocks/lead.json -2b32fe875f887d4a406700d35e0fe5a93548ebb7 data/c/tags/block/storage_blocks/raw_lead.json -0aafd338eaffcc3f48fb8dc9d18fc969318b06e0 data/c/tags/block/storage_blocks/raw_uranium.json -f8074cdbc6e2b560acb4e9da953b23f9825486a6 data/c/tags/block/storage_blocks/steel.json -a63487094743744be756ad497f483fcd4d11e9bc data/c/tags/fluid/uranium.json -fadb3957b979d82146790ef3550e38606760421e data/c/tags/item/armors/boots.json -0845acff015f78c494df2cd6754c5cff10d77c05 data/c/tags/item/armors/chestplates.json -b5d23f0bc26a4e3a72cde40f3c6d59c03c818b4d data/c/tags/item/armors/helmets.json -bebad856ee0f047735060f28544eb6149d8c2b20 data/c/tags/item/armors/leggings.json -4c65712ad229579aed33c75220c37f9a70134cb2 data/c/tags/item/dusts.json -25c93720c5221fac9aeb0ae47182ef59e0a0c2bb data/c/tags/item/dusts/coal.json -69b53861489d10b3a836be9812af97c999833470 data/c/tags/item/dusts/uranium.json -75f0600da4891d0f4a3329fb44cac6c4945a0b49 data/c/tags/item/glass_blocks.json -81d5270bd69ab7d6ffef70dc7867a498202eb4b4 data/c/tags/item/ingots.json -30fa647448df4131c1d6460756f18583a493ee31 data/c/tags/item/ingots/lead.json -24bc6e0cdae825d9e5d1500567ae81d83c15a88d data/c/tags/item/ingots/steel.json -3245aa72f5bb5f83632ab05f449e8a2d576ac386 data/c/tags/item/nuggets.json -41ff866ec94383906342a0d1594554e3063b9d0f data/c/tags/item/nuggets/lead.json -1ec402fda0c91947be220066973f79f3e522663f data/c/tags/item/nuggets/steel.json -925cb97bc13b3122fe17e59ff3ec2fe4d1eaacd5 data/c/tags/item/ores/lead.json -bad88bea18fec41c7ad6fa4d396feacc0346a137 data/c/tags/item/ores/uranium.json -cdebf2b4eabcf71ee4566b7fbf22f18990a4e06b data/c/tags/item/raw_materials.json -610ed700de0886bcb4b1c90100c35f3034c53940 data/c/tags/item/raw_materials/lead.json -03a88f0d9f44d3c338b82bf92b22a14dec490bef data/c/tags/item/raw_materials/uranium.json -cdebf2b4eabcf71ee4566b7fbf22f18990a4e06b data/c/tags/item/raw_ores.json -c1ad472460350e6abd024de7785cd870dad05cd9 data/c/tags/item/rods.json -a7258ae3454252e874b324fbd81b880ce52759c4 data/c/tags/item/storage_blocks/lead.json -2b32fe875f887d4a406700d35e0fe5a93548ebb7 data/c/tags/item/storage_blocks/raw_lead.json -0aafd338eaffcc3f48fb8dc9d18fc969318b06e0 data/c/tags/item/storage_blocks/raw_uranium.json -f8074cdbc6e2b560acb4e9da953b23f9825486a6 data/c/tags/item/storage_blocks/steel.json -8875ba7215b30d75573e3dcfe46e0b690b1d7f2f data/minecraft/tags/block/azalea_root_replaceable.json -af9bc48c0e6af58ad85da029e03b09d0c14c3b24 data/minecraft/tags/block/campfires.json -3206babfa42429478935375acd710b4028884941 data/minecraft/tags/block/dragon_transparent.json -8875ba7215b30d75573e3dcfe46e0b690b1d7f2f data/minecraft/tags/block/dripstone_replaceable_blocks.json -3206babfa42429478935375acd710b4028884941 data/minecraft/tags/block/fire.json -75f0600da4891d0f4a3329fb44cac6c4945a0b49 data/minecraft/tags/block/impermeable.json -8875ba7215b30d75573e3dcfe46e0b690b1d7f2f data/minecraft/tags/block/lush_ground_replaceable.json -e84d8e1fa924bec3e226b8917b4973b9629a5f52 data/minecraft/tags/block/mineable/axe.json -6322947de3a2a75c644193b3f760465786ada55a data/minecraft/tags/block/mineable/pickaxe.json -a7d4278d8a39649c8b658ad2f3f1d092cb012bdf data/minecraft/tags/block/mineable/shovel.json -8875ba7215b30d75573e3dcfe46e0b690b1d7f2f data/minecraft/tags/block/moss_replaceable.json -41d3382a5f829a516326fa59334529abffdc8fb2 data/minecraft/tags/block/needs_diamond_tool.json -38aa0fddd24ec7dde10f1e2804328660a2019ac8 data/minecraft/tags/block/needs_iron_tool.json -70955c444f864b4cf76dc7494195b95cec0c0775 data/minecraft/tags/block/slabs.json -f730ea13c5c0e367d6108fee0d47d10e8c39f3f7 data/minecraft/tags/block/stairs.json -a584f04787aadc06749c484b53947d4f78fccb96 data/minecraft/tags/block/walls.json -2535c56fd6376328fbca0528562ecc2046a3b655 data/minecraft/tags/entity_type/fall_damage_immune.json -a63487094743744be756ad497f483fcd4d11e9bc data/minecraft/tags/fluid/lava.json -70955c444f864b4cf76dc7494195b95cec0c0775 data/minecraft/tags/item/slabs.json -f730ea13c5c0e367d6108fee0d47d10e8c39f3f7 data/minecraft/tags/item/stairs.json -a584f04787aadc06749c484b53947d4f78fccb96 data/minecraft/tags/item/walls.json diff --git a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e index b90e23b..06d8a0a 100644 --- a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e +++ b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e @@ -1,8 +1,9 @@ -// 1.21.1 2025-11-11T13:47:08.3478244 Recipes +// 1.21.1 2026-08-15T15:38:30.2704532 Recipes 817eb6c9cc23cc6579dfe3793a9b4c82917d0dea data/createnuclear/advancement/recipes/misc/blasting/lead_ingot_for_lead.json -9bdc07b5aa3b5309fd0023b267e4a861adc0f1b3 data/createnuclear/advancement/recipes/misc/blasting/lead_ingot_for_lead_ore.json +d6139c79fa1a5730291086403e961f46d0b2d2aa data/createnuclear/advancement/recipes/misc/blasting/lead_ingot_for_lead_ore.json 531e75db303ab55e6fee923af2088a7fd1ee3123 data/createnuclear/advancement/recipes/misc/blasting/lead_ingot_for_raw_lead.json -010aef79a85e1e86d5f0ca20f3bc9673c520425a data/createnuclear/advancement/recipes/misc/blasting/raw_uranium_for_uranium_ore.json +f22e3f793d8adb3916bd4c2aa64c63f11c8bb74e data/createnuclear/advancement/recipes/misc/blasting/nitrogen_concentrate_for_nitrogen_concentrate.json +9577f63cd6e2387c61d4da77f73cbb3de9d28b2a data/createnuclear/advancement/recipes/misc/blasting/raw_uranium_for_uranium_ore.json 2d5a511ce08e8868caef61b8ccba1d47e8c2e8b8 data/createnuclear/advancement/recipes/misc/crafting/crafting/lead_block_from_compacting.json f63c279b2fdac7e2661280105d5a3840c1885b5c data/createnuclear/advancement/recipes/misc/crafting/crafting/lead_ingot_from_compacting.json d24c3b8a3362c17deadf33dfd2c82a69f5aeed26 data/createnuclear/advancement/recipes/misc/crafting/crafting/lead_ingot_from_decompacting.json @@ -11,16 +12,22 @@ c8ed2bb75937ada5b2dc28fb20a2ff30cfaa95a1 data/createnuclear/advancement/recipes/ c830f80e84bf41ef607567b535b1cd433b7c3fa2 data/createnuclear/advancement/recipes/misc/crafting/crafting/steel_ingot_from_compacting.json d247b5a7d2aa590656b7b19e1a34b5fde4b3c044 data/createnuclear/advancement/recipes/misc/crafting/crafting/steel_ingot_from_decompacting.json d69c6172541372cdf494aad76cffc609edd87e61 data/createnuclear/advancement/recipes/misc/crafting/crafting/steel_nugget_from_decompacting.json +0b24b21c14de1d79dbcc67ad96f757f003f5f81c data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_block_from_compacting.json +4ac420b1272d463e20c5f45b29c0062685432cd4 data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_ingot_from_compacting.json +b6860539f21d48bfc43bcdab5cbb4087419b8aa0 data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_ingot_from_decompacting.json +4642823d9dbdc24e6a7d354492511bdbc0bf9966 data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_nugget_from_decompacting.json c72b09dcbf03429201f475fc848debdba898931a data/createnuclear/advancement/recipes/misc/crafting/crafting/white_cloth.json 38a7237ebdaa8fc63e2860b4e19053ccc9bb2714 data/createnuclear/advancement/recipes/misc/crafting/crafting/white_cloth_wool.json 572db9bd6741ae0f5fe035ac53ceec45c869eb05 data/createnuclear/advancement/recipes/misc/smelting/lead_ingot_for_lead.json -d468ba59b25ddbffeb5a3a1e298f02e93246bc87 data/createnuclear/advancement/recipes/misc/smelting/lead_ingot_for_lead_ore.json +4f3fa347dfe3ed7cfc3923caa01cce9a751c22ca data/createnuclear/advancement/recipes/misc/smelting/lead_ingot_for_lead_ore.json 77cdcf8ebae5a8146f7c1ceb39567a9f83ab4c62 data/createnuclear/advancement/recipes/misc/smelting/lead_ingot_for_raw_lead.json -181b98bed073bdbbf3a20bb3d0d886057359da9e data/createnuclear/advancement/recipes/misc/smelting/raw_uranium_for_uranium_ore.json +6c00d3701cf637fa20148b4740856769057c9fd6 data/createnuclear/advancement/recipes/misc/smelting/nitrogen_concentrate_for_nitrogen_concentrate.json +4b0ca3ef1b014593997d9ff66c6e988092df1413 data/createnuclear/advancement/recipes/misc/smelting/raw_uranium_for_uranium_ore.json 6b6936bf71a27ec4e5fbad575971f7a87685e03f data/createnuclear/recipe/blasting/lead_ingot_for_lead.json -2e8b61aeb37329a5a1d20a4032cfa0972b3aa35b data/createnuclear/recipe/blasting/lead_ingot_for_lead_ore.json +ffb8d145685b0734a0f9880266049333c59adb63 data/createnuclear/recipe/blasting/lead_ingot_for_lead_ore.json caf2536990c02b52965faf41000479d173ae5ce3 data/createnuclear/recipe/blasting/lead_ingot_for_raw_lead.json -43584c0fb02633ea6ada2b24cea19560ac9e5498 data/createnuclear/recipe/blasting/raw_uranium_for_uranium_ore.json +6a46fd45b7623bb32be4be34ce2276cfb05e288c data/createnuclear/recipe/blasting/nitrogen_concentrate_for_nitrogen_concentrate.json +843e56a2c7edbb2b193cdcdec0eafae299e5b055 data/createnuclear/recipe/blasting/raw_uranium_for_uranium_ore.json dbca4445a4f024da2c2cc7c88e885639964800d4 data/createnuclear/recipe/crafting/crafting/lead_block_from_compacting.json 9c8258c26e0028851e583b7278122d3e36bcd77f data/createnuclear/recipe/crafting/crafting/lead_ingot_from_compacting.json ac1aafbe0f6261f8cf77462fdc7e6ebbffac5431 data/createnuclear/recipe/crafting/crafting/lead_ingot_from_decompacting.json @@ -29,9 +36,14 @@ fd535efce0c108d879e5a1f13aface5586fc3127 data/createnuclear/recipe/crafting/craf 1e73c963f7b256f77962139e91dbd6eaede3d228 data/createnuclear/recipe/crafting/crafting/steel_ingot_from_compacting.json 000385de7b8a84be8a42ecbc2e486e47978593e6 data/createnuclear/recipe/crafting/crafting/steel_ingot_from_decompacting.json 6f664e863b1a0333d16c20d3aacddd54e6f785fb data/createnuclear/recipe/crafting/crafting/steel_nugget_from_decompacting.json +d05377c40c6e1fd590f70d641549d1538066dde5 data/createnuclear/recipe/crafting/crafting/thorium_block_from_compacting.json +b0fe3a17994bb82d1f95253af2be0f2dbf5af04a data/createnuclear/recipe/crafting/crafting/thorium_ingot_from_compacting.json +19413a166da34c4f7138c758597098d6d2ca6196 data/createnuclear/recipe/crafting/crafting/thorium_ingot_from_decompacting.json +7504b59dbc116ff0362a9dc40437b37f56ae19d9 data/createnuclear/recipe/crafting/crafting/thorium_nugget_from_decompacting.json 79cb57ce627b9d1d4fe1f8874eccb2c5890ac1d8 data/createnuclear/recipe/crafting/crafting/white_cloth.json 38730b7c9d20af2d734457d15429a31913f926a6 data/createnuclear/recipe/crafting/crafting/white_cloth_wool.json b63c594645138909f08b9d2e587b08534c58b319 data/createnuclear/recipe/smelting/lead_ingot_for_lead.json -8dc067a59870db19ecdac45dca24aedfe2f89eb4 data/createnuclear/recipe/smelting/lead_ingot_for_lead_ore.json +9e5baea2e7897ea8294b1af515aa4f8cc6861ec6 data/createnuclear/recipe/smelting/lead_ingot_for_lead_ore.json 4608b430898214bae0648f7a2383bd9d49aeac8e data/createnuclear/recipe/smelting/lead_ingot_for_raw_lead.json -e4e201f37ebd694e4cc9a0acc6b76231504d0a4b data/createnuclear/recipe/smelting/raw_uranium_for_uranium_ore.json +78a1035e66960224af77af912804f14d15c3cd30 data/createnuclear/recipe/smelting/nitrogen_concentrate_for_nitrogen_concentrate.json +396997d4316b704109f6b6b0d8395d0ea57c309e data/createnuclear/recipe/smelting/raw_uranium_for_uranium_ore.json diff --git a/src/generated/resources/.cache/abc32a97b4e744838610c53dbbbaaf9f7d29a557 b/src/generated/resources/.cache/abc32a97b4e744838610c53dbbbaaf9f7d29a557 new file mode 100644 index 0000000..00d9391 --- /dev/null +++ b/src/generated/resources/.cache/abc32a97b4e744838610c53dbbbaaf9f7d29a557 @@ -0,0 +1,45 @@ +// 1.21.1 2026-08-16T15:11:03.8351655 Create Nuclear Advancements +ebf411a60f05043ea055e71f3ca186f1594c1dba data/createnuclear/advancement/absolute_zero.json +f2a761e7119d577ba470b2138e47bd4da621e703 data/createnuclear/advancement/anti_radiation_armor.json +22f2184726b7c4cb7be266711edcf91d10125308 data/createnuclear/advancement/automatic_uranium.json +2f54751fd7b850e790329345c6b1f8e68200fced data/createnuclear/advancement/avoiding_cancer.json +9846c243f0268eedba554e27d99c6fa8e2e6f5aa data/createnuclear/advancement/chemistry_101.json +d36106297b2e7069b101485a100782e0c77c0eaf data/createnuclear/advancement/chill_out.json +2e1dec8ed4682e81f54d9d914398b913c787079b data/createnuclear/advancement/coal_dust.json +d3674e376a832d98e791f49b39acc7a3dd9042e2 data/createnuclear/advancement/craft_enriching_campfire.json +f585e512a1e957e1b2e605763477b30a3aca790f data/createnuclear/advancement/crunchy_uranium.json +d505479bb4fe4bd1aa7d98a1ff31547164a62d29 data/createnuclear/advancement/cryogenic_baptism.json +fe60e614421886d1f192894225e648b8d95f044e data/createnuclear/advancement/dye_anti_radiation_armor.json +4851034c637144841755d30a8b34558949ddad03 data/createnuclear/advancement/enriched_yellowcake.json +087af3c8878cc40353cbbc13dfe826713afaffaf data/createnuclear/advancement/feeding_the_reactor.json +ce355f77f692c24dd0de94b607c4b6e59b075b95 data/createnuclear/advancement/fueling_the_reactor.json +5dee175af7f777b7bb1570a7fe90cee736df6128 data/createnuclear/advancement/getting_concentrated.json +f05c9e4301b8f27a4ea9f47d837ce0278db21d50 data/createnuclear/advancement/graphene.json +8bebd812c141937025dd8c6f57f24b74b20283fc data/createnuclear/advancement/graphite_rod.json +b11898a3d5315921dde1644758571d7b95c0b6ce data/createnuclear/advancement/lead_ingot.json +88c87da2924234c30a30139f374de46a64465ac2 data/createnuclear/advancement/no_time_to_die.json +9133fe9d5d8014b10a52be3e5e3a77c06d6e1fdd data/createnuclear/advancement/raw_lead.json +82b7f690fe9e440ab2ade0393477c6b6f2314b35 data/createnuclear/advancement/raw_thorium.json +a36b76d7a5379c24a5ad9ca303c5bb9d5d077e4a data/createnuclear/advancement/raw_uranium.json +850b2c28cd50225a091b2d4576bec80f5ffebf7c data/createnuclear/advancement/reactor_blueprint.json +8c097387f4fdf9762d6c62bcc95309fa34e1e21c data/createnuclear/advancement/reactor_casing.json +22e20cedebe2e0cec9a01f18982b351342a830be data/createnuclear/advancement/reactor_controller.json +4b1e572d041327a6710c9de5a209176e1d6d0dc9 data/createnuclear/advancement/reactor_cooler.json +731a41f1bd6289513da429ef87341c4e629d24c3 data/createnuclear/advancement/reactor_core.json +36156f60d09a48852295fc7b7dbe9006d5ff597a data/createnuclear/advancement/reactor_frame.json +b60fb4eda3db03e754d26377940f0e28780cae25 data/createnuclear/advancement/reinforced_glass.json +0288ebaaf2a637ea12d9b4746f57046a9d1ef43b data/createnuclear/advancement/root.json +911aa5207efe7ab395259ca59c3ab6c6fc90c407 data/createnuclear/advancement/silence_the_core.json +fd962b874a6c7e2bf406eee4d9509372af2563e0 data/createnuclear/advancement/steel_ingot.json +94d885bd7fa5b5614c3fcfba95019712591919be data/createnuclear/advancement/t1.json +75f1ed25a0b82120229268f0368391cc57f743fc data/createnuclear/advancement/t2.json +e2af771ef077c45aead85102cd7f82d726d52848 data/createnuclear/advancement/t3.json +a5630b09d394ece8957072ff417fdce9c1b23add data/createnuclear/advancement/thorium_dust.json +0c60740d7926315536a79f1d6d8655b5b62b38e7 data/createnuclear/advancement/thorium_ingot.json +4d64dd8b0409f207de06cde8d16a486b83ca6e29 data/createnuclear/advancement/thorium_liquid.json +cbcdc3cf056bd7dc23814728cf1aad1368ff3beb data/createnuclear/advancement/thorium_rod.json +ad3f8ed835cc52b0770f96f325a5d572e1cba6cd data/createnuclear/advancement/unlimited_power.json +c5f7517a7b40a1ac9ef161243c88396b9162cdf6 data/createnuclear/advancement/uranium_liquid.json +7c0c35534aa3a69cf2d7b811975c3ceebd2e5e03 data/createnuclear/advancement/uranium_powder.json +8350e570b8b0850f4d45aa55f7a7b893c35ec06a data/createnuclear/advancement/uranium_rod.json +15318081ea582b5cf9b45025d32254b0c1dcc0f9 data/createnuclear/advancement/yellowcake.json diff --git a/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 b/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 deleted file mode 100644 index e4d8a88..0000000 --- a/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 +++ /dev/null @@ -1,17 +0,0 @@ -// 1.21.1 2025-12-13T13:14:00.9168398 Create's Processing Recipes -d85b9bde5850d362e8e708e56c0d082f0fc3303f data/createnuclear/recipe/compacting/uranium_fluid_to_yellowcake.json -a11a9d69b96e4cd1b748cab33dabd6a2964ad6ac data/createnuclear/recipe/crushing/coal.json -49a7aa4b43af0c778821d656ec594f80c362fab5 data/createnuclear/recipe/crushing/crushed_raw_uranium.json -371ca9bbe8682870942f1b41ec361b8a51be2f44 data/createnuclear/recipe/enriched/enriched_yellowcake.json -fdf6d4fce42373c414542289a73f0e206ff438f2 data/createnuclear/recipe/enriched/enriching_campfire.json -0c8d7d7eae585213bb7b3bb8ca4749dabafc27a3 data/createnuclear/recipe/item_application/reactor_casing_from_steel_and_brass_casing.json -10d6c0cbf1bb303c25fb266c623577d541047251 data/createnuclear/recipe/item_application/reactor_input_from_hopper_and_reactor_casing.json -be6e4c7d7a82de8b5398ec0e7b0b193568946f05 data/createnuclear/recipe/item_application/reactor_output_from_shaft_and_reactor_casing.json -93bc6d7a40f2ccb89d8d5703c4b0f6c576d5caf8 data/createnuclear/recipe/mixing/steel.json -e52ccded5e0955ab39320129fce8f78d50f52250 data/createnuclear/recipe/mixing/uranium_fluid.json -4e362c3fb35c7a4cf946fda91958fe6b84a59e04 data/createnuclear/recipe/pressing/graphene.json -c1e0e107502e875ee5befc176335cbd1cef7e04d data/create/recipe/crushing/granite.json -724e99e5db2392644021999b8a694a9b20d8ea0e data/create/recipe/crushing/raw_copper.json -9fbd393caf0c74349e1afffe27a9b594de657e91 data/create/recipe/crushing/raw_uranium_block.json -efc52853cb5199a32131c8eccb6d42adff342365 data/create/recipe/crushing/raw_zinc.json -282966a4f127d86ed7a46757303d70314d44be47 data/create/recipe/splashing/crushed_raw_lead.json diff --git a/src/generated/resources/.cache/ccee8ac36b69081c3d5a985b1ab20579b9fbc4da b/src/generated/resources/.cache/ccee8ac36b69081c3d5a985b1ab20579b9fbc4da deleted file mode 100644 index e1566ba..0000000 --- a/src/generated/resources/.cache/ccee8ac36b69081c3d5a985b1ab20579b9fbc4da +++ /dev/null @@ -1,27 +0,0 @@ -// 1.21.1 2025-06-14T16:01:31.6962597 CreateNuclear's Advancements -cbbad2b1d3ec778592ecf506e26aaa727a997851 data/createnuclear/advancement/anti_radiation_armor.json -a21321d07d837d6b66a7888a66949ae199761c36 data/createnuclear/advancement/automatic_uranium.json -2e1dec8ed4682e81f54d9d914398b913c787079b data/createnuclear/advancement/coal_dust.json -3ff03565d4208d6804bce330b9dc7ce83d170628 data/createnuclear/advancement/dye_anti_radiation_armor.json -4851034c637144841755d30a8b34558949ddad03 data/createnuclear/advancement/enriched_yellowcake.json -c31186a865d9b98d6a8e227148e561eb06faac50 data/createnuclear/advancement/full_anti_radiation_armor.json -f05c9e4301b8f27a4ea9f47d837ce0278db21d50 data/createnuclear/advancement/graphene.json -8bebd812c141937025dd8c6f57f24b74b20283fc data/createnuclear/advancement/graphite_rod.json -b11898a3d5315921dde1644758571d7b95c0b6ce data/createnuclear/advancement/lead_ingot.json -9133fe9d5d8014b10a52be3e5e3a77c06d6e1fdd data/createnuclear/advancement/raw_lead.json -a36b76d7a5379c24a5ad9ca303c5bb9d5d077e4a data/createnuclear/advancement/raw_uranium.json -850b2c28cd50225a091b2d4576bec80f5ffebf7c data/createnuclear/advancement/reactor_blueprint.json -8c097387f4fdf9762d6c62bcc95309fa34e1e21c data/createnuclear/advancement/reactor_casing.json -22e20cedebe2e0cec9a01f18982b351342a830be data/createnuclear/advancement/reactor_controller.json -682f409310e9139d3cabbf3c8ddd1463d5d47865 data/createnuclear/advancement/reactor_cooler.json -731a41f1bd6289513da429ef87341c4e629d24c3 data/createnuclear/advancement/reactor_core.json -63c1d45a3cec0e3bfe157f877fcb50274c45394c data/createnuclear/advancement/reactor_frame.json -b49e62b222b018d1259fc0fb1e1b705fd3af03ae data/createnuclear/advancement/reactor_input.json -b86dd29986e4dd9c978d16aa52e9d9e45dd55594 data/createnuclear/advancement/reactor_output.json -b60fb4eda3db03e754d26377940f0e28780cae25 data/createnuclear/advancement/reinforced_glass.json -bb596e3a589fcd22d634a7a88bca21b6f0a1308b data/createnuclear/advancement/root.json -fd962b874a6c7e2bf406eee4d9509372af2563e0 data/createnuclear/advancement/steel_ingot.json -c5f7517a7b40a1ac9ef161243c88396b9162cdf6 data/createnuclear/advancement/uranium_liquid.json -7c0c35534aa3a69cf2d7b811975c3ceebd2e5e03 data/createnuclear/advancement/uranium_powder.json -8350e570b8b0850f4d45aa55f7a7b893c35ec06a data/createnuclear/advancement/uranium_rod.json -15318081ea582b5cf9b45025d32254b0c1dcc0f9 data/createnuclear/advancement/yellowcake.json diff --git a/src/generated/resources/.cache/fed443662143001aeb5341375f6f5ef31d10baea b/src/generated/resources/.cache/fed443662143001aeb5341375f6f5ef31d10baea index 217a979..0d99c43 100644 --- a/src/generated/resources/.cache/fed443662143001aeb5341375f6f5ef31d10baea +++ b/src/generated/resources/.cache/fed443662143001aeb5341375f6f5ef31d10baea @@ -1,10 +1,27 @@ -// 1.21.1 2025-06-14T16:01:31.6723028 CreateNuclear Generated Registry Entries +// 1.21.1 2026-08-16T19:20:18.1740496 CreateNuclear Generated Registry Entries +46e263393c1672a180bc12b99f9e39adf22e66b5 data/createnuclear/createnuclear/fluids/type/fallback.json +2837d5ecbd5735f39c1fac545469486e09c502e0 data/createnuclear/createnuclear/fluids/type/nitrogen.json +152a58adb9f86e1c9fac62fd2095ba8413142568 data/createnuclear/createnuclear/fluids/type/water.json +15403b1cee46d300af2247a08485c04ccd80cfc0 data/createnuclear/createnuclear/rods/type/fallback.json +74de56c37a28ab632a6ffc161475bcec85de68e2 data/createnuclear/damage_type/fan_radiation.json +dfb5a22341ff4202e85ca8cdf9b6ec95c6e280d1 data/createnuclear/damage_type/radiation.json 5b42761cb26db47a6ad47ff3c84820f9fd541477 data/createnuclear/neoforge/biome_modifier/lead_ore.json +11b96fb02b86323e62801eb592485cd110c6ad8d data/createnuclear/neoforge/biome_modifier/nitrate_ore.json 2ab7262c3d16fb07daf01cf4ca7d07a04f2238b8 data/createnuclear/neoforge/biome_modifier/striated_ores_overworld.json +39052943da1229795ee268fa3cae5a10ea8d9030 data/createnuclear/neoforge/biome_modifier/thorium_ore.json cda82c4dbdb27f3b37d1faeda2ddbb211f76c15c data/createnuclear/neoforge/biome_modifier/uranium_ore.json -b68555f371c9700aa4ecfa9370b010de8fe25b60 data/createnuclear/worldgen/configured_feature/lead_ore.json +9ecfcf402b61fd7aadf249d428a098e959306b5c data/createnuclear/worldgen/biome/irradiated_land.json +d9a89f0f1804d33867b4e0c28cbe0cf69ce131f5 data/createnuclear/worldgen/configured_feature/lead_ore.json +c3bb421f6bf5a02b09a178d4d1f003679b86c919 data/createnuclear/worldgen/configured_feature/nitrate_ore.json 4f11c0a518c0de7857919983fc638ba551c6630a data/createnuclear/worldgen/configured_feature/striated_ores_overworld.json +aaa284a4e57635bf05f4539125b33a2f9176ed5b data/createnuclear/worldgen/configured_feature/thorium_ore.json b0e1ee7314412507fd7346cb48b29d105f6186ad data/createnuclear/worldgen/configured_feature/uranium_ore.json -d45ed5f7008864ba4f60c409038ad428a280fd7f data/createnuclear/worldgen/placed_feature/lead_ore.json -f26be417cb34461ecb180e77a9a749eaaf4c9880 data/createnuclear/worldgen/placed_feature/striated_ores_overworld.json -bed936158c61471513252910d9e3b0e2de610f1a data/createnuclear/worldgen/placed_feature/uranium_ore.json +59d61c02881d710b0426a0955f6945b7a12d219f data/createnuclear/worldgen/density_function/irradiated/erosion.json +59d61c02881d710b0426a0955f6945b7a12d219f data/createnuclear/worldgen/density_function/irradiated/final_density.json +7f5f110a211b82bc22627b2f901c5f3c6a1265dd data/createnuclear/worldgen/noise/irradiated/erosion.json +ea836bafce53bcb743cb2de5ba38271291483865 data/createnuclear/worldgen/noise_settings/irradiated_noise.json +f11d981e79cf92130a47ad564925d7be26ffbc0b data/createnuclear/worldgen/placed_feature/lead_ore.json +e69f61cbb4bf2c50a6123ddc87c024c801bb78d1 data/createnuclear/worldgen/placed_feature/nitrate_ore.json +d0e47433fc86ee2acd9dde56f0465aae54fe5fe0 data/createnuclear/worldgen/placed_feature/striated_ores_overworld.json +5e64cf339847e8c89e4bbb94a2382262a0ce66ac data/createnuclear/worldgen/placed_feature/thorium_ore.json +148db47005efc228a743e41fd60011b8bff8e78a data/createnuclear/worldgen/placed_feature/uranium_ore.json diff --git a/src/generated/resources/assets/createnuclear/blockstates/deepslate_nitrate_ore.json b/src/generated/resources/assets/createnuclear/blockstates/deepslate_nitrate_ore.json new file mode 100644 index 0000000..0b75136 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/deepslate_nitrate_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "createnuclear:block/deepslate_nitrate_ore" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/deepslate_thorium_ore.json b/src/generated/resources/assets/createnuclear/blockstates/deepslate_thorium_ore.json new file mode 100644 index 0000000..9effc25 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/deepslate_thorium_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "createnuclear:block/deepslate_thorium_ore" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/nitrate_ore.json b/src/generated/resources/assets/createnuclear/blockstates/nitrate_ore.json new file mode 100644 index 0000000..2f14544 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/nitrate_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "createnuclear:block/nitrate_ore" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/nitrogen.json b/src/generated/resources/assets/createnuclear/blockstates/nitrogen.json new file mode 100644 index 0000000..113fb23 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/nitrogen.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "createnuclear:block/nitrogen" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/raw_thorium_block.json b/src/generated/resources/assets/createnuclear/blockstates/raw_thorium_block.json new file mode 100644 index 0000000..626939b --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/raw_thorium_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "createnuclear:block/raw_thorium_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/reactor_alarm.json b/src/generated/resources/assets/createnuclear/blockstates/reactor_alarm.json new file mode 100644 index 0000000..1a4f203 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/reactor_alarm.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "createnuclear:block/reactor_alarm" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/reactor_controller.json b/src/generated/resources/assets/createnuclear/blockstates/reactor_controller.json index 28a903c..cbd0a7c 100644 --- a/src/generated/resources/assets/createnuclear/blockstates/reactor_controller.json +++ b/src/generated/resources/assets/createnuclear/blockstates/reactor_controller.json @@ -1,33 +1,63 @@ { "variants": { - "assembled=false,facing=east": { - "model": "createnuclear:block/reactor/controller/block", + "active=false,assembled=false,facing=east": { + "model": "createnuclear:block/reactor/controller/off", "y": 270 }, - "assembled=false,facing=north": { - "model": "createnuclear:block/reactor/controller/block", + "active=false,assembled=false,facing=north": { + "model": "createnuclear:block/reactor/controller/off", "y": 180 }, - "assembled=false,facing=south": { - "model": "createnuclear:block/reactor/controller/block" + "active=false,assembled=false,facing=south": { + "model": "createnuclear:block/reactor/controller/off" }, - "assembled=false,facing=west": { - "model": "createnuclear:block/reactor/controller/block", + "active=false,assembled=false,facing=west": { + "model": "createnuclear:block/reactor/controller/off", "y": 90 }, - "assembled=true,facing=east": { - "model": "createnuclear:block/reactor/controller/block", + "active=false,assembled=true,facing=east": { + "model": "createnuclear:block/reactor/controller/standby", "y": 270 }, - "assembled=true,facing=north": { - "model": "createnuclear:block/reactor/controller/block", + "active=false,assembled=true,facing=north": { + "model": "createnuclear:block/reactor/controller/standby", "y": 180 }, - "assembled=true,facing=south": { - "model": "createnuclear:block/reactor/controller/block" + "active=false,assembled=true,facing=south": { + "model": "createnuclear:block/reactor/controller/standby" }, - "assembled=true,facing=west": { - "model": "createnuclear:block/reactor/controller/block", + "active=false,assembled=true,facing=west": { + "model": "createnuclear:block/reactor/controller/standby", + "y": 90 + }, + "active=true,assembled=false,facing=east": { + "model": "createnuclear:block/reactor/controller/off", + "y": 270 + }, + "active=true,assembled=false,facing=north": { + "model": "createnuclear:block/reactor/controller/off", + "y": 180 + }, + "active=true,assembled=false,facing=south": { + "model": "createnuclear:block/reactor/controller/off" + }, + "active=true,assembled=false,facing=west": { + "model": "createnuclear:block/reactor/controller/off", + "y": 90 + }, + "active=true,assembled=true,facing=east": { + "model": "createnuclear:block/reactor/controller/on", + "y": 270 + }, + "active=true,assembled=true,facing=north": { + "model": "createnuclear:block/reactor/controller/on", + "y": 180 + }, + "active=true,assembled=true,facing=south": { + "model": "createnuclear:block/reactor/controller/on" + }, + "active=true,assembled=true,facing=west": { + "model": "createnuclear:block/reactor/controller/on", "y": 90 } } diff --git a/src/generated/resources/assets/createnuclear/blockstates/reactor_fluid_input.json b/src/generated/resources/assets/createnuclear/blockstates/reactor_fluid_input.json new file mode 100644 index 0000000..2ada65a --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/reactor_fluid_input.json @@ -0,0 +1,26 @@ +{ + "variants": { + "facing=down": { + "model": "createnuclear:block/reactor/fluid_input/fluid_input_vertical", + "x": 180 + }, + "facing=east": { + "model": "createnuclear:block/reactor/fluid_input/fluid_input", + "y": 270 + }, + "facing=north": { + "model": "createnuclear:block/reactor/fluid_input/fluid_input", + "y": 180 + }, + "facing=south": { + "model": "createnuclear:block/reactor/fluid_input/fluid_input" + }, + "facing=up": { + "model": "createnuclear:block/reactor/fluid_input/fluid_input_vertical" + }, + "facing=west": { + "model": "createnuclear:block/reactor/fluid_input/fluid_input", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/reactor_input.json b/src/generated/resources/assets/createnuclear/blockstates/reactor_input.json deleted file mode 100644 index d6e0558..0000000 --- a/src/generated/resources/assets/createnuclear/blockstates/reactor_input.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "variants": { - "facing=east": { - "model": "createnuclear:block/reactor/input/block", - "y": 270 - }, - "facing=north": { - "model": "createnuclear:block/reactor/input/block", - "y": 180 - }, - "facing=south": { - "model": "createnuclear:block/reactor/input/block" - }, - "facing=west": { - "model": "createnuclear:block/reactor/input/block", - "y": 90 - } - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/reactor_rod_input.json b/src/generated/resources/assets/createnuclear/blockstates/reactor_rod_input.json new file mode 100644 index 0000000..37ee320 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/reactor_rod_input.json @@ -0,0 +1,26 @@ +{ + "variants": { + "facing=down": { + "model": "createnuclear:block/reactor/rod_input/rod_input_vertical", + "x": 180 + }, + "facing=east": { + "model": "createnuclear:block/reactor/rod_input/rod_input", + "y": 270 + }, + "facing=north": { + "model": "createnuclear:block/reactor/rod_input/rod_input", + "y": 180 + }, + "facing=south": { + "model": "createnuclear:block/reactor/rod_input/rod_input" + }, + "facing=up": { + "model": "createnuclear:block/reactor/rod_input/rod_input_vertical" + }, + "facing=west": { + "model": "createnuclear:block/reactor/rod_input/rod_input", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/thorium.json b/src/generated/resources/assets/createnuclear/blockstates/thorium.json new file mode 100644 index 0000000..007ce08 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/thorium.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "createnuclear:block/thorium" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/thorium_block.json b/src/generated/resources/assets/createnuclear/blockstates/thorium_block.json new file mode 100644 index 0000000..cb8fa63 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/thorium_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "createnuclear:block/thorium_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/blockstates/thorium_ore.json b/src/generated/resources/assets/createnuclear/blockstates/thorium_ore.json new file mode 100644 index 0000000..c976ca1 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/blockstates/thorium_ore.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "createnuclear:block/thorium_ore" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/lang/en_ud.json b/src/generated/resources/assets/createnuclear/lang/en_ud.json index b6eee9a..590b33c 100644 --- a/src/generated/resources/assets/createnuclear/lang/en_ud.json +++ b/src/generated/resources/assets/createnuclear/lang/en_ud.json @@ -1,24 +1,46 @@ { - "advancement.createnuclear.anti_radiation_armor": "ɹoɯɹⱯ uoıʇɐıpɐɹ ıʇuⱯ", + "advancement.createnuclear.absolute_zero": "oɹǝZ ǝʇnןosqⱯ", + "advancement.createnuclear.absolute_zero.desc": "uǝboɹʇıu pınbıן uıɐʇqo oʇ ǝʇɐɹʇuǝɔuoɔ uǝboɹʇıu pǝןooɔ xıW", + "advancement.createnuclear.anti_radiation_armor": "ɹoɯɹⱯ uoıʇɐıpɐᴚ ıʇuⱯ", "advancement.createnuclear.anti_radiation_armor.desc": "uoıʇɐıpɐɹ ɯoɹɟ ɟןǝsɹnoʎ ʇɔǝʇoɹd oʇ ǝɔǝıd ɹoɯɹɐ uoıʇɐıpɐɹ-ıʇuɐ ʇsɹıɟ ɹnoʎ ʇɟɐɹƆ", "advancement.createnuclear.automatic_uranium": "ɯnıuɐɹ∩ buıʇɐɯoʇnⱯ", "advancement.createnuclear.automatic_uranium.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\nbuıssǝɔoɹd ɯnıuɐɹn ɔıʇɐɯoʇnɐ ǝɥʇ buısn ɹǝpʍod ɯnıuɐɹn ǝɯos uıɐʇqO", + "advancement.createnuclear.avoiding_cancer": "pǝɹǝʌoƆ ɟןǝsɹnoʎ dǝǝʞ ʇsǝᗺ", + "advancement.createnuclear.avoiding_cancer.desc": "ǝɯıʇ ʇsɹıɟ ǝɥʇ ɹoɟ ɹoɯɹɐ uoıʇɐıpɐɹ-ıʇuɐ dınbƎ", + "advancement.createnuclear.chemistry_101": "ʇI buıɥsnɹƆ", + "advancement.createnuclear.chemistry_101.desc": "ǝʇɐɹʇıu uıɐʇqo oʇ ǝuoʇsǝɯıן ɥsnɹɔ ɹo ǝɹo ǝʇɐɹʇıu ǝuıW", + "advancement.createnuclear.chill_out": "ʇnO ןןıɥƆ", + "advancement.createnuclear.chill_out.desc": "uoıʇɔɐɟǝnbıן ɹoɟ ʇı ǝɹɐdǝɹd oʇ ǝʇɐɹʇuǝɔuoɔ uǝboɹʇıu uʍop ןooƆ", "advancement.createnuclear.coal_dust": "ʇsnᗡ ןɐoƆ", "advancement.createnuclear.coal_dust.desc": "ןɐıɹǝʇɐɯ buıʇɟɐɹɔ ʎǝʞ ɐ 'ʇsnp ןɐoɔ uıɐʇqo oʇ ןɐoɔɹɐɥɔ ɹo ןɐoɔ ɥsnɹƆ", + "advancement.createnuclear.craft_enriching_campfire": "¿ǝʞoɯS ǝʞɐW ʇɐɥ⟘ sǝoᗡ", + "advancement.createnuclear.craft_enriching_campfire.desc": "ǝɹıɟdɯɐƆ buıɥɔıɹuƎ uɐ ʇɟɐɹƆ", + "advancement.createnuclear.crunchy_uranium": "ʇɔǝdxƎ noʎ pıᗡ ʇɐɥM", + "advancement.createnuclear.crunchy_uranium.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\n¿¿ ʇɐɥʍ pıp noʎ ˙˙˙˙˙oɹᗺ", + "advancement.createnuclear.cryogenic_baptism": "ǝɹoɯʎuⱯ ʇǝǝℲ ʎW ןǝǝℲ ʇ,uɐɔ I", + "advancement.createnuclear.cryogenic_baptism.desc": ")ʇuǝɯǝɔuɐʌpⱯ uǝppıH(ㄥ§\nǝɯıʇ ʇsɹıɟ ǝɥʇ ɹoɟ uǝboɹʇıu pınbıן ǝɥʇ uı ɯıʍS", "advancement.createnuclear.dye_anti_radiation_armor": "ɹoɯɹⱯ ʎW dɯıԀ", "advancement.createnuclear.dye_anti_radiation_armor.desc": "ɹoןoɔ ʎuɐ oʇ ɹoɯɹɐ uoıʇɐıpɐɹ ıʇuɐ ɹnoʎ ǝʎᗡ", "advancement.createnuclear.enriched_yellowcake": "ǝʞɐɔʍoןןǝʎ buıɔuɐɥuƎ", "advancement.createnuclear.enriched_yellowcake.desc": "ןnɟɹǝʍod ǝɹoɯ ʇı ǝʞɐɯ puɐ ǝʞɐɔʍoןןǝʎ ɥɔıɹuǝ oʇ uɐɟ ɐ ǝs∩", - "advancement.createnuclear.full_anti_radiation_armor": "pǝʇɔǝʇoɹԀ ʎןןnℲ", - "advancement.createnuclear.full_anti_radiation_armor.desc": "uoıʇɐıpɐɹ ɯoɹɟ ɟןǝsɹnoʎ ʇɔǝʇoɹd ʎןןnɟ oʇ ɹoɯɹɐ uoıʇɐıpɐɹ-ıʇuɐ ɟo ʇǝs ןןnɟ ɐ ɹɐǝM", + "advancement.createnuclear.feeding_the_reactor": "ɹoʇɔɐǝᴚ ǝɥ⟘ buıpǝǝℲ", + "advancement.createnuclear.feeding_the_reactor.desc": "ɹoʇɔɐǝɹ ɹnoʎ oʇuı spoɹ buıןooɔ puɐ buıʇɐǝɥ pǝǝɟ oʇ ʇnduI poᴚ ɹoʇɔɐǝᴚ ɐ ʇɟɐɹƆ", + "advancement.createnuclear.fueling_the_reactor": "ɹoʇɔɐǝᴚ ǝɥ⟘ buıןǝnℲ", + "advancement.createnuclear.fueling_the_reactor.desc": "ɹoʇɔɐǝɹ ɹnoʎ oʇuı ʇuɐןooɔ pınbıן pǝǝɟ oʇ ʇnduI pınןℲ ɹoʇɔɐǝᴚ ɐ ʇɟɐɹƆ", + "advancement.createnuclear.getting_concentrated": "pǝʇɐɹʇuǝɔuoƆ buıʇʇǝ⅁", + "advancement.createnuclear.getting_concentrated.desc": "ǝʇɐɹʇuǝɔuoɔ uǝboɹʇıu uıɐʇqo oʇ ǝɔɐuɹnɟ ʇsɐןq ɐ uı ǝʇɐɹʇıu ʇןǝɯS", "advancement.createnuclear.graphene": "ǝuǝɥdɐɹ⅁", "advancement.createnuclear.graphene.desc": "ǝuǝɥdɐɹb ǝʇɐǝɹɔ oʇ ʇsnp ןɐoɔ ssǝɹԀ", "advancement.createnuclear.graphite_rod": "sǝuO ǝsoɥ⟘ ʇǝbɹoℲ ʇ,uoᗡ", "advancement.createnuclear.graphite_rod.desc": "spoɹ ǝʇıɥdɐɹb ǝʞɐɯ oʇ ɹǝʇɟɐɹɔ ןɐɔıuɐɥɔǝɯ ɐ uı sʇobuı ןǝǝʇs puɐ ǝuǝɥdɐɹb ǝuıqɯoƆ", - "advancement.createnuclear.lead_ingot": "ʇobuı pɐǝꞀ", + "advancement.createnuclear.lead_ingot": "ʇobuI pɐǝꞀ", "advancement.createnuclear.lead_ingot.desc": "ʇobuı pɐǝן ɐ uıɐʇqo oʇ pɐǝן ʍɐɹ ɐ ʇןǝɯS", + "advancement.createnuclear.no_time_to_die": "ǝıᗡ o⟘ ǝɯı⟘ oN", + "advancement.createnuclear.no_time_to_die.desc": "¡ WOOOᗺⱯʞ ǝɥʇ ǝɹoɟǝq ɹoʇɔɐǝɹ ǝɥʇ doʇS", "advancement.createnuclear.raw_lead": "pɐǝꞀ ʍɐᴚ", "advancement.createnuclear.raw_lead.desc": "ǝɹo pɐǝן buıuıɯ ʎq pɐǝן ʍɐɹ ǝɯos uıɐʇqO", + "advancement.createnuclear.raw_thorium": "ʍoן⅁ s,ɯnıɹoɥ⟘", + "advancement.createnuclear.raw_thorium.desc": "buıssǝɔoɹd ɹǝɥʇɹnɟ ɹoɟ ɯnıɹoɥʇ ʍɐɹ uıɐʇqo oʇ ǝɹo ɯnıɹoɥʇ ǝuıW", "advancement.createnuclear.raw_uranium": "ɹǝʍoԀ ʍɐᴚ ǝɥ⟘", "advancement.createnuclear.raw_uranium.desc": "buıssǝɔoɹd ɹǝɥʇɹnɟ ɹoɟ ɯnıuɐɹn ʍɐɹ uıɐʇqo oʇ ǝɹo ɯnıuɐɹn ǝuıW", "advancement.createnuclear.reactor_blueprint": "ɹǝʍoԀ ɹoℲ ʇuıɹdǝnןᗺ", @@ -29,20 +51,34 @@ "advancement.createnuclear.reactor_controller.desc": "ɹoʇɔɐǝɹ ɹnoʎ ǝʇɐןnbǝɹ puɐ ǝbɐuɐɯ oʇ ɹǝןןoɹʇuoɔ ɹoʇɔɐǝɹ ɐ ʇɟɐɹƆ", "advancement.createnuclear.reactor_cooler": "ɹoʇɔɐǝᴚ ǝɥ⟘ buıןooƆ", "advancement.createnuclear.reactor_cooler.desc": "ɹoʇɔɐǝɹ ɹnoʎ ןooɔ oʇ ɹǝןooɔ ɹoʇɔɐǝɹ ɐ ʇɟɐɹƆ", - "advancement.createnuclear.reactor_core": "ɹǝʍoԀ ɟo ǝɹoƆ", + "advancement.createnuclear.reactor_core": "ɹǝʍoԀ ɟO ǝɹoƆ", "advancement.createnuclear.reactor_core.desc": "ɹoʇɔɐǝɹ ɹɐǝןɔnu ɹnoʎ ɟo ʎbɹǝuǝ ןןnɟ ǝɥʇ ssǝuɹɐɥ oʇ ǝɹoɔ ɹoʇɔɐǝɹ ǝɥʇ ʇɟɐɹƆ", "advancement.createnuclear.reactor_frame": "ǝɯɐɹℲ ɹoʇɔɐǝᴚ", "advancement.createnuclear.reactor_frame.desc": "ɹoʇɔɐǝɹ ɹɐǝןɔnu ɹnoʎ pןınq oʇ ǝɯɐɹɟ ɹoʇɔɐǝɹ ɐ ʇɟɐɹƆ", - "advancement.createnuclear.reactor_input": "ɹoʇɔɐǝᴚ ǝɥ⟘ buıןǝnℲ", - "advancement.createnuclear.reactor_input.desc": "ɹoʇɔɐǝɹ ɹnoʎ oʇuı spoɹ ǝʇıɥdɐɹb puɐ ɯnıuɐɹn pǝǝɟ oʇ ʇnduı ɹoʇɔɐǝɹ ɐ ʇɟɐɹƆ", - "advancement.createnuclear.reactor_output": "ʇndʇnO ɹǝʍoԀ", - "advancement.createnuclear.reactor_output.desc": "ɹoʇɔɐǝɹ ɹnoʎ ʎq pǝɔnpoɹd ʎbɹǝuǝ ǝɥʇ ɹǝɟsuɐɹʇ oʇ ʇndʇno ɹoʇɔɐǝɹ ɐ ʇɟɐɹƆ", "advancement.createnuclear.reinforced_glass": "ssɐן⅁ pǝɔɹoɟuıǝᴚ", "advancement.createnuclear.reinforced_glass.desc": "ǝɯıʇ ʇsɹıɟ ǝɥʇ ɹoɟ ssɐןb pǝɔɹoɟuıǝɹ ǝɯos ʇɟɐɹƆ", "advancement.createnuclear.root": "ʎǝuɹnoſ ɹɐǝןɔnN ǝɥ⟘ buıʇɹɐʇS", "advancement.createnuclear.root.desc": "ɹǝpʍod ɯnıuɐɹn ʇsɹıɟ ɹnoʎ ʇǝb puɐ ʎbɹǝuǝ ɹɐǝןɔnu ɟo sɔısɐq ǝɥʇ ʞɔoןu∩", + "advancement.createnuclear.silence_the_core": "¡ ǝsıoN ɥɔnW oS sǝʞɐW ʇI", + "advancement.createnuclear.silence_the_core.desc": "ǝɯıʇ ʇsɹıɟ ǝɥʇ ɹoɟ ɯɹɐןɐ ǝɥʇ punos", "advancement.createnuclear.steel_ingot": "ʇobuI ןǝǝʇS", "advancement.createnuclear.steel_ingot.desc": "sʇobuı ןǝǝʇs ǝʇɐǝɹɔ oʇ sʇobuı uoɹı puɐ ʇsnp ןɐoɔ ǝuıqɯoƆ", + "advancement.createnuclear.t1": "Ɩ⟘ ɹǝןןoɹʇuoƆ ɹoʇɔɐǝᴚ", + "advancement.createnuclear.t1.desc": "ɹoʇɔɐǝᴚ ɹɐǝןɔnN Ɩ ɹǝıʇ ɐ pןınᗺ", + "advancement.createnuclear.t2": "ᄅ⟘ ɹǝןןoɹʇuoƆ ɹoʇɔɐǝᴚ", + "advancement.createnuclear.t2.desc": "ɹoʇɔɐǝᴚ ɹɐǝןɔnN ᄅ ɹǝıʇ ɐ pןınᗺ", + "advancement.createnuclear.t3": "Ɛ⟘ ɹǝןןoɹʇuoƆ ɹoʇɔɐǝᴚ", + "advancement.createnuclear.t3.desc": "ɹoʇɔɐǝᴚ ɹɐǝןɔnN Ɛ ɹǝıʇ ɐ pןınᗺ", + "advancement.createnuclear.thorium_dust": "ɯnıɹoɥ⟘ pǝɹǝpʍoԀ", + "advancement.createnuclear.thorium_dust.desc": "buıuıɟǝɹ ɹǝɥʇɹnɟ ɹoɟ ǝɹɐdǝɹd oʇ ʇsnp oʇuı ɯnıɹoɥʇ ʍɐɹ ɥsnɹƆ", + "advancement.createnuclear.thorium_ingot": "ɯnıɹoɥ⟘ pǝʇɔɐdɯoƆ", + "advancement.createnuclear.thorium_ingot.desc": "ʇobuı ɯnıɹoɥʇ ɐ ǝʇɐǝɹɔ oʇ pınbıן ɯnıɹoɥʇ ʇɔɐdɯoƆ", + "advancement.createnuclear.thorium_liquid": "ɯnıɹoɥ⟘ uǝʇןoW", + "advancement.createnuclear.thorium_liquid.desc": "ʇsnp ɯnıɹoɥʇ buıxıɯ ʎq pınbıן ɯnıɹoɥʇ ǝɯos uıɐʇqO", + "advancement.createnuclear.thorium_rod": "ʞɔıʇS ǝnןᗺ Ɐ ʇɐɥM", + "advancement.createnuclear.thorium_rod.desc": "ǝɯıʇ ʇsɹıɟ ǝɥʇ ɹoɟ poɹ ɯnıɹoɥʇ ɐ ʇɟɐɹƆ", + "advancement.createnuclear.unlimited_power": "ɹǝʍoԀ pǝʇıɯıןu∩", + "advancement.createnuclear.unlimited_power.desc": "ɹoʇɔɐǝɹ ɹnoʎ ʎq pǝɔnpoɹd ʎbɹǝuǝ ǝɥʇ ʇɔɐɹʇxǝ oʇ ʇndʇnO ɹoʇɔɐǝᴚ ɐ ʇɟɐɹƆ", "advancement.createnuclear.uranium_liquid": "pınbıꞀ o⟘ pıןoS buıuɹn⟘", "advancement.createnuclear.uranium_liquid.desc": "ɹǝpʍod ɯnıuɐɹn buıxıɯ ʎq pınbıן ɯnıuɐɹn ǝɯos uıɐʇqO", "advancement.createnuclear.uranium_powder": "ɯnıuɐɹ∩ pǝɹǝpʍoԀ", @@ -51,6 +87,7 @@ "advancement.createnuclear.uranium_rod.desc": "ɹǝʇɟɐɹɔ ןɐɔıuɐɥɔǝɯ ɐ uı ǝʞɐɔʍoןןǝʎ pǝɥɔıɹuǝ buısn poɹ ɯnıuɐɹn ʇsɹıɟ ɹnoʎ ǝʇɐǝɹƆ", "advancement.createnuclear.yellowcake": "ssǝɔoɹԀ ǝʞɐɔʍoןןǝʎ ǝɥ⟘", "advancement.createnuclear.yellowcake.desc": "ǝʞɐɔʍoןןǝʎ ǝʇɐǝɹɔ oʇ pınbıן ɯnıuɐɹn ʇɔɐdɯoƆ", + "attribute.name.createnuclear.generic.irradiated_resistance": "ǝɔuɐʇsısǝᴚ uoıʇɐıpɐᴚ", "block.createnuclear.autunite": "ǝʇıunʇnⱯ", "block.createnuclear.autunite_pillar": "ɹɐןןıԀ ǝʇıunʇnⱯ", "block.createnuclear.cut_autunite": "ǝʇıunʇnⱯ ʇnƆ", @@ -62,6 +99,8 @@ "block.createnuclear.cut_autunite_stairs": "sɹıɐʇS ǝʇıunʇnⱯ ʇnƆ", "block.createnuclear.cut_autunite_wall": "ןןɐM ǝʇıunʇnⱯ ʇnƆ", "block.createnuclear.deepslate_lead_ore": "ǝɹO pɐǝꞀ ǝʇɐןsdǝǝᗡ", + "block.createnuclear.deepslate_nitrate_ore": "ǝɹO ǝʇɐɹʇıN ǝʇɐןsdǝǝᗡ", + "block.createnuclear.deepslate_thorium_ore": "ǝɹO ɯnıɹoɥ⟘ ǝʇɐןsdǝǝᗡ", "block.createnuclear.deepslate_uranium_ore": "ǝɹO ɯnıuɐɹ∩ ǝʇɐןsdǝǝᗡ", "block.createnuclear.enriched_soul_soil": "ןıoS ןnoS pǝɥɔıɹuƎ", "block.createnuclear.enriched_soul_soil.tooltip.summary": "˙‾ǝɹıɟ uǝǝɹb‾ ɐ ǝʞɐɯ oʇ ʇsnظ ɹo ǝɹıɟdɯɐɔ pǝɥɔıɹuǝ ‾ʇɟɐɹɔ‾ oʇ pǝsn ǝq uɐƆ˙‾ǝɹıɟ pǝɥɔıɹuǝ‾ ǝʇɐǝɹɔ oɥʍ ʞɔoןq ‾ʎןuo‾ ǝɥ⟘", @@ -70,12 +109,16 @@ "block.createnuclear.layered_autunite": "ǝʇıunʇnⱯ pǝɹǝʎɐꞀ", "block.createnuclear.lead_block": "ʞɔoןᗺ pɐǝꞀ", "block.createnuclear.lead_ore": "ǝɹO pɐǝꞀ", + "block.createnuclear.nitrate_ore": "ǝɹO ǝʇɐɹʇıN", + "block.createnuclear.nitrogen": "uǝboɹʇıN", "block.createnuclear.polished_cut_autunite": "ǝʇıunʇnⱯ ʇnƆ pǝɥsıןoԀ", "block.createnuclear.polished_cut_autunite_slab": "qɐןS ǝʇıunʇnⱯ ʇnƆ pǝɥsıןoԀ", "block.createnuclear.polished_cut_autunite_stairs": "sɹıɐʇS ǝʇıunʇnⱯ ʇnƆ pǝɥsıןoԀ", "block.createnuclear.polished_cut_autunite_wall": "ןןɐM ǝʇıunʇnⱯ ʇnƆ pǝɥsıןoԀ", "block.createnuclear.raw_lead_block": "ʞɔoןᗺ pɐǝꞀ ʍɐᴚ", + "block.createnuclear.raw_thorium_block": "ʞɔoןᗺ ɯnıɹoɥ⟘ ʍɐᴚ", "block.createnuclear.raw_uranium_block": "ʞɔoןᗺ ɯnıuɐɹ∩ ʍɐᴚ", + "block.createnuclear.reactor_alarm": "ɯɹɐןⱯ ɹoʇɔɐǝᴚ", "block.createnuclear.reactor_casing": "buısɐƆ ɹoʇɔɐǝᴚ", "block.createnuclear.reactor_casing.tooltip.summary": "‾ɹoʇɔɐǝɹ‾ ǝɥʇ pןınq oʇ pǝsn ‾ʞɔoןᗺ‾", "block.createnuclear.reactor_controller": "ɹǝןןoɹʇuoƆ ɹoʇɔɐǝᴚ", @@ -86,9 +129,12 @@ "block.createnuclear.reactor_cooler.tooltip.summary": "‾ɹoʇɔɐǝɹ‾ ǝɥʇ pןınq oʇ pǝsn ‾ʞɔoןᗺ‾", "block.createnuclear.reactor_core": "ǝɹoƆ ɹoʇɔɐǝᴚ", "block.createnuclear.reactor_core.tooltip.summary": "‾ɹoʇɔɐǝɹ‾ ǝɥʇ pןınq oʇ pǝsn ‾ʞɔoןᗺ‾", + "block.createnuclear.reactor_fluid_input": "ʇnduI pınןℲ ɹoʇɔɐǝᴚ", + "block.createnuclear.reactor_fluid_input.tooltip.behaviour1": "˙‾buıʇɐǝɥɹǝʌo‾ pıoʌɐ puɐ ‾ɹoʇɔɐǝᴚ ǝɥ⟘‾ ɹǝʍod oʇ sǝıʇıʇuɐnb ǝbɹɐן uı ‾uǝboɹʇıN pınbıꞀ‾ ɹo ‾ɹǝʇɐM‾ ʇɹǝsuI", + "block.createnuclear.reactor_fluid_input.tooltip.condition1": "pǝןqɯǝssɐ sı ɹoʇɔɐǝɹ ǝɥʇ uǝɥM", + "block.createnuclear.reactor_fluid_input.tooltip.summary": "˙ɹoʇɔɐǝᴚ ǝɥʇ oʇuı ‾uǝboɹʇıN pınbıꞀ‾ ɹo ‾ɹǝʇɐM‾ ʇɹǝsuı oʇ pǝsn ǝq uɐɔ ʇɐɥʇ ‾ʞɔoןq‾ ɐ sı ‾ʇnduI pınןℲ ɹoʇɔɐǝᴚ ǝɥ⟘‾", "block.createnuclear.reactor_frame": "ǝɯɐɹℲ ɹoʇɔɐǝᴚ", "block.createnuclear.reactor_frame.tooltip.summary": "‾ɹoʇɔɐǝɹ‾ ǝɥʇ pןınq oʇ pǝsn ‾ʞɔoןᗺ‾", - "block.createnuclear.reactor_input": "ʇnduI ɹoʇɔɐǝᴚ", "block.createnuclear.reactor_input.tooltip.behaviour1": " ‾ɹoʇɔɐǝɹ ǝɥʇ‾ ɹǝʍod oʇ sǝıʇıʇuɐnb ǝbɹɐן uı spoɹ ‾ǝuǝɥdɐɹb‾ puɐ ‾ɯnıuɐɹn‾ ʇɹǝsuI", "block.createnuclear.reactor_input.tooltip.condition1": "pǝןqɯǝssɐ sı ɹoʇɔɐǝᴚ ǝɥʇ uǝɥM", "block.createnuclear.reactor_input.tooltip.summary": "‾ɹoʇɔɐǝᴚ‾ ǝɥʇ oʇuı spoɹ ‾ǝuǝɥdɐɹ⅁‾ puɐ ‾ɯnıuɐɹ∩‾ ʇɹǝsuı oʇ pǝsn ǝq uɐɔ ʇɐɥʇ ‾ʞɔoןq‾ ɐ sı ‾ʇnduI ɹoʇɔɐǝᴚ ǝɥ⟘‾", @@ -96,147 +142,268 @@ "block.createnuclear.reactor_output.tooltip.behaviour1": "‾ʇndʇno ɹoʇɔɐǝɹ‾ ǝɥʇ oʇ ‾ʇɟɐɥs‾ buıɥɔɐʇʇɐ ʎq ɹoʇɔɐǝɹ ǝɥʇ ʎq ǝɔnpoɹd ‾ʎbɹǝuǝ ǝɥʇ ʇɔɐɹʇxǝ‾ uɐɔ noʎ", "block.createnuclear.reactor_output.tooltip.condition1": "ʎbɹǝuǝ ǝɔnpoɹd ɹoʇɔɐǝɹ ǝɥʇ uǝɥM", "block.createnuclear.reactor_output.tooltip.summary": "‾ɹoʇɔɐǝᴚ‾ ǝɥʇ ʎq pǝʇɐɹǝuǝb ʎbɹǝuǝ ןɐɔıuɐɥɔǝɯ ǝɥʇ ʇɔɐɹʇxǝ oʇ pǝsn ǝq uɐɔ ʇɐɥʇ ‾ʞɔoןq‾ ɐ sı ‾ʇndʇnO ɹoʇɔɐǝᴚ ǝɥ⟘‾", + "block.createnuclear.reactor_rod_input": "ʇnduI poᴚ ɹoʇɔɐǝᴚ", "block.createnuclear.reinforced_glass": "ssɐן⅁ pǝɔɹoɟuıǝᴚ", "block.createnuclear.small_autunite_brick_slab": "qɐןS ʞɔıɹᗺ ǝʇıunʇnⱯ ןןɐɯS", "block.createnuclear.small_autunite_brick_stairs": "sɹıɐʇS ʞɔıɹᗺ ǝʇıunʇnⱯ ןןɐɯS", "block.createnuclear.small_autunite_brick_wall": "ןןɐM ʞɔıɹᗺ ǝʇıunʇnⱯ ןןɐɯS", "block.createnuclear.small_autunite_bricks": "sʞɔıɹᗺ ǝʇıunʇnⱯ ןןɐɯS", "block.createnuclear.steel_block": "ʞɔoןᗺ ןǝǝʇS", + "block.createnuclear.thorium": "ɯnıɹoɥ⟘", + "block.createnuclear.thorium_block": "ʞɔoןᗺ ɯnıɹoɥ⟘", + "block.createnuclear.thorium_ore": "ǝɹO ɯnıɹoɥ⟘", "block.createnuclear.uranium": "ɯnıuɐɹ∩", "block.createnuclear.uranium_ore": "ǝɹO ɯnıuɐɹ∩", "create.recipe.fan_enriched.fan": "ǝɹıℲ pǝɥɔıɹuƎ puıɥǝq uɐℲ", + "create.recipe.fan_snow_powder.fan": "ʍouS ɹǝpʍoԀ puıɥǝq uɐℲ", + "createnuclear.display_source.cooler": "ɹǝןooƆ ɹoʇɔɐǝᴚ", + "createnuclear.display_source.fuel": "ןǝnℲ ɹoʇɔɐǝᴚ", + "createnuclear.display_source.heat": "ʇɐǝH ɹoʇɔɐǝᴚ", + "createnuclear.display_source.heat.rotation": "WԀᴚ", + "createnuclear.display_source.heat.type": "ןǝʌǝן ʇɐǝH", + "createnuclear.display_source.heat.value": "Ὁ", + "createnuclear.display_source.liquid": "ןǝʌǝꞀ pınbıꞀ", + "createnuclear.display_source.liquid_level": "ןǝʌǝꞀ pınbıꞀ ɹoʇɔɐǝᴚ", + "createnuclear.display_source.reactor.active": "ƎΛI⟘ƆⱯ", + "createnuclear.display_source.reactor.cooler": " :ɹǝןooƆ", + "createnuclear.display_source.reactor.fluid": " :pınןℲ", + "createnuclear.display_source.reactor.for_reactor_status": "snʇɐʇs ɹoʇɔɐǝɹ ɹoɟ", + "createnuclear.display_source.reactor.fuel": " :ןǝnℲ", + "createnuclear.display_source.reactor.heat": " :ʇɐǝH", + "createnuclear.display_source.reactor.idle": "ƎꞀᗡI", + "createnuclear.display_source.reactor.mode.gauge": "sǝbnɐ⅁", + "createnuclear.display_source.reactor.mode.normal": "ןɐɯɹoN", + "createnuclear.display_source.reactor.mode.percent": "sǝbɐʇuǝɔɹǝԀ", + "createnuclear.display_source.reactor.mode.value": "sǝnןɐΛ", + "createnuclear.display_source.reactor.no_controller": "punoɟ ɹǝןןoɹʇuoƆ ɹoʇɔɐǝᴚ oN", + "createnuclear.display_source.reactor.not_enough_space": " ǝɔɐds ɥbnouǝ ʇoN", + "createnuclear.display_source.reactor.size": " :ɹǝı⟘", + "createnuclear.display_source.reactor.size.large": "ǝbɹɐꞀ", + "createnuclear.display_source.reactor.size.medium": "ɯnıpǝW", + "createnuclear.display_source.reactor.size.small": "ןןɐɯS", + "createnuclear.display_source.reactor.status": " :snʇɐʇS", + "createnuclear.display_source.reactor_controller_count_rod.cooled": "pǝןooƆ", + "createnuclear.display_source.reactor_controller_count_rod.fuel": "ןǝnℲ", + "createnuclear.display_source.reactor_count_rod": "uɹǝʇʇɐԀ uı poᴚ ʇunoƆ", + "createnuclear.display_source.reactor_summary": "ʎɹɐɯɯnS ɹoʇɔɐǝᴚ", + "createnuclear.display_source.reactor_summary.active": "ƎΛI⟘ƆⱯ", + "createnuclear.display_source.reactor_summary.coolant": ":ʇuɐןooƆ", + "createnuclear.display_source.reactor_summary.fuel": ":spoᴚ", + "createnuclear.display_source.reactor_summary.idle": "ƎꞀᗡI", + "createnuclear.display_source.reactor_summary.no_controller": "punoɟ ʇou ɹoʇɔɐǝᴚ", + "createnuclear.display_source.reactor_summary.status": ":snʇɐʇS", + "createnuclear.display_source.reactor_summary.temperature": ":dɯǝ⟘", + "createnuclear.display_source.size": "ǝzıS ɹoʇɔɐǝᴚ", "createnuclear.enriched.fan.recipe": "buıɥɔıɹuƎ ʞןnᗺ", + "createnuclear.generic.unit.count.rod": "poᴚ %s sʇunoƆ", + "createnuclear.generic.unit.countCooled.rod": "%d :poᴚ pǝןooƆ ʇunoƆ", + "createnuclear.generic.unit.countFuel.rod": "%d :poᴚ ןǝnℲ ʇunoƆ", + "createnuclear.generic.unit.fluid.value": "ᗺɯ", "createnuclear.generic.unit.heat": "Ὁ", + "createnuclear.generic.unit.heat.rotation": "WԀᴚ", + "createnuclear.generic.unit.heat.type": "%s :ןǝʌǝꞀ ʇɐǝH", + "createnuclear.generic.unit.heat.value": "Ὁ", + "createnuclear.generic.unit.liquid": "ԀIM", + "createnuclear.generic.unit.seconds": "s", "createnuclear.gui.reactor_controller.info_header.title": "ǝnןɐʌ ʇɐǝH", - "createnuclear.ponder.reactor.header": "ɹoʇɔɐǝɹ ǝɥʇ ɟo uoıʇɔnɹʇsuoƆ", - "createnuclear.ponder.reactor.text_1": "Ɩ ɹooןℲ", - "createnuclear.ponder.reactor.text_10": "ㄥ ɹooןℲ", - "createnuclear.ponder.reactor.text_2": "˙ɹoʇɔɐǝɹ ǝɥʇ ʎq pǝʇɐɹǝuǝb )∩S( ʎbɹǝuǝ ǝɥʇ sʇndʇno ʇɐɥʇ ʞɔoןq ǝɥʇ sı sıɥ⟘ :ʇndʇnO ɹoʇɔɐǝᴚ", - "createnuclear.ponder.reactor.text_3": "ᄅ ɹooןℲ", - "createnuclear.ponder.reactor.text_4": "Ɛ ɹooןℲ", - "createnuclear.ponder.reactor.text_5": "ㄣ ɹooןℲ", - "createnuclear.ponder.reactor.text_6": "˙ɹoʇɔɐǝɹ ǝɥʇ ǝʇɐɹǝdo oʇ spoɹ ǝʇıɥdɐɹb puɐ ɯnıuɐɹn sǝɹoʇs ʇɐɥʇ ʞɔoןq Ɐ :ʇnduI ɹoʇɔɐǝᴚ", - "createnuclear.ponder.reactor.text_7": "˙ɹǝʍod ǝʇɐɹǝuǝb oʇ pǝpǝǝu suoıʇɐןnɔןɐɔ ǝɥʇ ןןɐ sǝןpuɐɥ ʇı ؛ɹoʇɔɐǝɹ ǝɥʇ ǝʇɐɹǝdo oʇ ʞɔoןq ʇuɐʇɹodɯı ʇsoɯ ǝɥ⟘ :ɹǝןןoɹʇuoƆ ɹoʇɔɐǝᴚ", - "createnuclear.ponder.reactor.text_8": "ϛ ɹooןℲ", - "createnuclear.ponder.reactor.text_9": "9 ɹooןℲ", - "createnuclear.ponder.reactor_blueprint.header": "uoıʇɐʌıʇɔⱯ ɹǝןןoɹʇuoƆ", - "createnuclear.ponder.reactor_blueprint.text_1": "˙sןǝpoɯ ɔıɟıɔǝds oʇ buıpɹoɔɔɐ pǝɹnbıɟuoɔ ǝq oʇ ɹoʇɔɐǝɹ ǝɥʇ sʍoןןɐ ʇı ؛ʇuǝɯǝןǝ ʇuɐʇɹodɯı ʇsoɯ ǝɥʇ :ʇuıɹdǝnןᗺ ɹoʇɔɐǝᴚ", + "createnuclear.notification.reactor.assembled": "pǝןqɯǝssɐ uǝǝq sɐɥ ɹoʇɔɐǝᴚ", + "createnuclear.notification.reactor.critical_failure": "Ǝᴚ∩ꞀIⱯℲ ꞀⱯƆI⟘IᴚƆ", + "createnuclear.notification.reactor.destroyed": "ᗡƎʎOᴚ⟘SƎᗡ ᴚO⟘ƆⱯƎᴚ", + "createnuclear.notification.reactor.disassembled": "pǝןqɯǝssɐsıp uǝǝq sɐɥ ɹoʇɔɐǝᴚ", + "createnuclear.notification.reactor.imminent_explosion": "NOISOꞀԀXƎ ⟘NƎNIWWI", + "createnuclear.notification.reactor.meltdown_finished": "pǝʇǝןdɯoɔ uʍopʇןǝɯ ןɐɔıʇıɹƆ", + "createnuclear.notification.reactor.meltdown_in": " NI NMOᗡ⟘ꞀƎW ƎᴚOƆ", + "createnuclear.notification.reactor.overheating": "⅁NI⟘ⱯƎHᴚƎΛO ƎᴚOƆ :⅁NINᴚⱯM", + "createnuclear.notification.reactor.stabilized": "ᗡƎZIꞀIᗺⱯ⟘S ƎᴚOƆ", + "createnuclear.ponder.reactor_io_placement.header": "ʇuǝɯǝɔɐןԀ & uoıʇɔunℲ :O/I ɹoʇɔɐǝᴚ", + "createnuclear.ponder.reactor_io_placement.text_1": "˙ʎʇıןıqɐʇs ɹoɟ poᴚ buıןooƆ ǝuo puɐ 'ɹoʇɔɐǝɹ ǝɥʇ ʇɐǝɥ oʇ )ןǝnɟ( poᴚ buıʇɐǝH ǝuo pǝǝu ǝM ˙spoᴚ buıןooƆ ɹo buıʇɐǝH sǝɹoʇS :ʇnduI poᴚ", + "createnuclear.ponder.reactor_io_placement.text_2": "˙suoısoןdxǝ ʇuǝʌǝɹd oʇ poᴚ buıןooƆ ǝɥʇ ɹoɟ ǝuo puɐ poᴚ buıʇɐǝH ǝɥʇ ɹoɟ ǝuO ¡sʇnduı oʍʇ ʇsɐǝן ʇɐ pǝǝu ǝʍ ʎɥʍ sı sıɥ⟘ :ʇnduI poᴚ puoɔǝS", + "createnuclear.ponder.reactor_io_placement.text_3": "˙ǝpoןdxǝ ʇou sǝop ʇı ǝɹnsuǝ puɐ ɹoʇɔɐǝɹ ǝɥʇ ןooɔ oʇ pǝɹınbǝɹ osןɐ sı pınןℲ :ʇnduI pınןℲ", + "createnuclear.ponder.reactor_io_placement.text_4": "˙buıpoןdxǝ sʞsıɹ puɐ ǝןqɐʇsun sǝɯoɔǝq ɹoʇɔɐǝɹ ǝɥʇ uǝɥʍ punos ɐ sʇıɯƎ :)ןɐuoıʇdO( ɯɹɐןⱯ", + "createnuclear.ponder.reactor_io_placement.text_5": "˙ɯǝɥʇ uǝǝʍʇǝq ʎbɹǝuǝ ןɐʇoʇ ǝɥʇ ɥɔʇɐdsıp oʇ sʇndʇno ǝןdıʇןnɯ ǝɔɐןd uɐɔ noʎ ˙ʎbɹǝuǝ pǝʇɐɹǝuǝb ʇɔɐɹʇxǝ oʇ ʎɹɐssǝɔǝN :ʇndʇnO", + "createnuclear.ponder.reactor_io_placement.text_6": "˙ǝbpǝ uɐ uo ʇou sı ʇı sɐ buoן sɐ 'buısɐƆ ɹoʇɔɐǝᴚ ʎNⱯ ǝɔɐןdǝɹ uɐɔ sʞɔoןq ǝsǝɥ⟘", + "createnuclear.ponder.reactor_io_placement.text_7": "˙ǝɔɐɟɹns ʇɐןɟ ɹǝɥʇo ʎuɐ ɹo ɟooɹ ǝɥʇ uo ɹǝɥʇǝboʇ pǝdnoɹb ǝq uɐɔ ʎǝɥ⟘", + "createnuclear.ponder.reactor_t1.header": "Ɩ⟘ ɹoʇɔɐǝᴚ", + "createnuclear.ponder.reactor_t1.text_1": "Ɩ ɹooןℲ", + "createnuclear.ponder.reactor_t1.text_10": "˙)uoıʇɔunɟ & ʇuǝɯǝɔɐןd( sʞɔoןq ɯɹɐןⱯ puɐ O/I ɹoɟ ㄣ ǝbɐd ʞɔǝɥƆ :ǝʇoN", + "createnuclear.ponder.reactor_t1.text_2": "ᄅ ɹooןℲ", + "createnuclear.ponder.reactor_t1.text_3": "Ɛ ɹooןℲ", + "createnuclear.ponder.reactor_t1.text_4": "ㄣ ɹooןℲ", + "createnuclear.ponder.reactor_t1.text_5": "ʇı ʇɹɐʇs oʇ sǝob ʇuıɹdǝnןq ǝɥʇ ǝɹǝɥʍ ǝɔɐןd ǝɥʇ puɐ 'ɹoʇɔɐǝɹ ǝɥʇ ɟo uıɐɹq :ɹǝןןoɹʇuoƆ", + "createnuclear.ponder.reactor_t1.text_6": "ϛ ɹooןℲ", + "createnuclear.ponder.reactor_t1.text_7": "9 ɹooןℲ", + "createnuclear.ponder.reactor_t1.text_8": "ㄥ ɹooןℲ", + "createnuclear.ponder.reactor_t1.text_9": "puɐɥ uı ʇuıɹdǝnןq ǝɥʇ ɥʇıʍ ɹǝןןoɹʇuoɔ ǝɥʇ ʞɔıןɔ ʇɥbıɹ uǝɥʇ 'uɹǝʇʇɐd ǝɥʇ oʇ buıpuodsǝɹɹoɔ spoɹ puɐ pınbıן pǝǝu ןןıʍ noʎ ɹoʇɔɐǝɹ ǝɥʇ ʇɹɐʇs o⟘", + "createnuclear.ponder.reactor_t2.header": "ᄅ⟘ ɹoʇɔɐǝᴚ", + "createnuclear.ponder.reactor_t2.text_1": "Ɩ ɹooןℲ", + "createnuclear.ponder.reactor_t2.text_10": "6 ɹooןℲ", + "createnuclear.ponder.reactor_t2.text_11": "puɐɥ uı ʇuıɹdǝnןq ǝɥʇ ɥʇıʍ ɹǝןןoɹʇuoɔ ǝɥʇ ʞɔıןɔ ʇɥbıɹ uǝɥʇ 'uɹǝʇʇɐd ǝɥʇ oʇ buıpuodsǝɹɹoɔ spoɹ puɐ pınbıן pǝǝu ןןıʍ noʎ ɹoʇɔɐǝɹ ǝɥʇ ʇɹɐʇs o⟘", + "createnuclear.ponder.reactor_t2.text_12": "˙)uoıʇɔunɟ & ʇuǝɯǝɔɐןd( sʞɔoןq ɯɹɐןⱯ puɐ O/I ɹoɟ ㄣ ǝbɐd ʞɔǝɥƆ :ǝʇoN", + "createnuclear.ponder.reactor_t2.text_2": "ᄅ ɹooןℲ", + "createnuclear.ponder.reactor_t2.text_3": "Ɛ ɹooןℲ", + "createnuclear.ponder.reactor_t2.text_4": "ㄣ ɹooןℲ", + "createnuclear.ponder.reactor_t2.text_5": "ϛ ɹooןℲ", + "createnuclear.ponder.reactor_t2.text_6": "ʇı ʇɹɐʇs oʇ sǝob ʇuıɹdǝnןq ǝɥʇ ǝɹǝɥʍ ǝɔɐןd ǝɥʇ puɐ 'ɹoʇɔɐǝɹ ǝɥʇ ɟo uıɐɹq :ɹǝןןoɹʇuoƆ", + "createnuclear.ponder.reactor_t2.text_7": "9 ɹooןℲ", + "createnuclear.ponder.reactor_t2.text_8": "ㄥ ɹooןℲ", + "createnuclear.ponder.reactor_t2.text_9": "8 ɹooןℲ", + "createnuclear.ponder.reactor_t3.header": "Ɛ⟘ ɹoʇɔɐǝᴚ", + "createnuclear.ponder.reactor_t3.text_1": "Ɩ ɹooןℲ", + "createnuclear.ponder.reactor_t3.text_10": "6 ɹooןℲ", + "createnuclear.ponder.reactor_t3.text_11": "0Ɩ ɹooןℲ", + "createnuclear.ponder.reactor_t3.text_12": "ƖƖ ɹooןℲ", + "createnuclear.ponder.reactor_t3.text_13": "puɐɥ uı ʇuıɹdǝnןq ǝɥʇ ɥʇıʍ ɹǝןןoɹʇuoɔ ǝɥʇ ʞɔıןɔ ʇɥbıɹ uǝɥʇ 'uɹǝʇʇɐd ǝɥʇ oʇ buıpuodsǝɹɹoɔ spoɹ puɐ pınbıן pǝǝu ןןıʍ noʎ ɹoʇɔɐǝɹ ǝɥʇ ʇɹɐʇs o⟘", + "createnuclear.ponder.reactor_t3.text_14": "˙)uoıʇɔunɟ & ʇuǝɯǝɔɐןd( sʞɔoןq ɯɹɐןⱯ puɐ O/I ɹoɟ ㄣ ǝbɐd ʞɔǝɥƆ :ǝʇoN", + "createnuclear.ponder.reactor_t3.text_2": "ᄅ ɹooןℲ", + "createnuclear.ponder.reactor_t3.text_3": "Ɛ ɹooןℲ", + "createnuclear.ponder.reactor_t3.text_4": "ㄣ ɹooןℲ", + "createnuclear.ponder.reactor_t3.text_5": "ϛ ɹooןℲ", + "createnuclear.ponder.reactor_t3.text_6": "9 ɹooןℲ", + "createnuclear.ponder.reactor_t3.text_7": "ʇı ʇɹɐʇs oʇ sǝob ʇuıɹdǝnןq ǝɥʇ ǝɹǝɥʍ ǝɔɐןd ǝɥʇ puɐ 'ɹoʇɔɐǝɹ ǝɥʇ ɟo uıɐɹq :ɹǝןןoɹʇuoƆ", + "createnuclear.ponder.reactor_t3.text_8": "ㄥ ɹooןℲ", + "createnuclear.ponder.reactor_t3.text_9": "8 ɹooןℲ", + "createnuclear.reactor.debug.label.alarm": "ɯɹɐןⱯ", + "createnuclear.reactor.debug.label.fluid_input": "ʇnduI pınןℲ", + "createnuclear.reactor.debug.label.input": "ʇnduI", + "createnuclear.reactor.debug.label.output": "ʇndʇnO", + "createnuclear.reactor.debug.registered_position": "%s @ pǝɹǝʇsıbǝɹ ", + "createnuclear.reactor.debug.summary": "pıןɐʌ %s 'pǝɹǝʇsıbǝɹ %s :%s", + "createnuclear.reactor.debug.title": "--- sɔıʇsoubɐıp ɹoʇɔɐǝᴚ ---", + "createnuclear.reactor.debug.valid_position": "%s @ pıןɐʌ ", + "createnuclear.snow_powder.fan.recipe": "uɐɟ ɔıuǝboʎɹƆ", + "createnuclear.subtitle.alarm/alarm": "dooꞀ ɯɹɐןⱯ ɹoʇɔɐǝᴚ", + "createnuclear.subtitle.alarm/reactor_alarm": "ɯɹɐןⱯ ɹoʇɔɐǝᴚ", + "createnuclear.subtitle.biomes/wasteland": "puɐןǝʇsɐM", + "createnuclear.subtitle.explosion/large_nuclear_explosion": "uoısoןdxƎ ɹɐǝןɔnN ǝbɹɐꞀ", + "createnuclear.subtitle.explosion/main": "uıɐW uoısoןdxƎ ɹɐǝןɔnN", + "createnuclear.subtitle.explosion/nuclear_explosion": "uoısoןdxƎ ɹɐǝןɔnN", + "createnuclear.subtitle.explosion/nuclear_explosion_rumble": "ǝןqɯnᴚ uoısoןdxƎ ɹɐǝןɔnN", + "createnuclear.subtitle.explosion/ringing": "buıbuıᴚ uoısoןdxƎ ɹɐǝןɔnN", + "createnuclear.subtitle.explosion/rumble": "ǝןqɯnᴚ uoısoןdxƎ ɹɐǝןɔnN", + "createnuclear.subtitle.explosion/shockwave": "ǝʌɐʍʞɔoɥS uoısoןdxƎ ɹɐǝןɔnN", + "createnuclear.subtitle.geiger/high": "ɥbıH ɹǝbıǝ⅁", + "createnuclear.subtitle.geiger/low": "ʍoꞀ ɹǝbıǝ⅁", + "createnuclear.subtitle.geiger/medium": "ɯnıpǝW ɹǝbıǝ⅁", + "createnuclear.subtitle.reacteur/activation": "uoıʇɐʌıʇɔⱯ ɹoʇɔɐǝᴚ", + "createnuclear.subtitle.reacteur/assemble_deassemble/motor_assemble": "ǝןqɯǝssⱯ ɹoʇoW", + "createnuclear.subtitle.reacteur/assemble_deassemble/motor_disassemble": "ǝןqɯǝssɐsıᗡ ɹoʇoW", + "createnuclear.subtitle.reacteur/running": "buıuunᴚ ɹoʇɔɐǝᴚ", + "createnuclear.subtitle.reacteur/shut_off": "ɟɟO ʇnɥS ɹoʇɔɐǝᴚ", + "createnuclear.tooltip.baseRodHeat": "Ὁ %d :ʇɐǝH poᴚ ǝsɐᗺ", + "createnuclear.tooltip.cloth.color": "%s :ǝɔǝıd ɹoɯɹɐ ɟo ɹoןoƆ", + "createnuclear.tooltip.fluid": " %s :pınןℲ", + "createnuclear.tooltip.fluid.amount": "qɯ %d", + "createnuclear.tooltip.fluid.none": " ǝuoN :pınןℲ", "createnuclear.tooltip.heatLevel": "ןǝʌǝꞀ ʇɐǝH", "createnuclear.tooltip.heatLevel.caution": "uoıʇnɐƆ", "createnuclear.tooltip.heatLevel.danger": "ɹǝbuɐᗡ", "createnuclear.tooltip.heatLevel.none": "ǝuoN", "createnuclear.tooltip.heatLevel.safety": "ʎʇǝɟɐS", "createnuclear.tooltip.heatLevel.warning": "buıuɹɐM", - "createnuclear.tooltip.item.graphene.rod": " :poᴚ ǝʇıɥdɐɹ⅁", + "createnuclear.tooltip.item.cooled.rod": " :poᴚ ɹǝןooƆ", + "createnuclear.tooltip.item.empty.rod": " :sɯǝʇI ʇnduI", + "createnuclear.tooltip.item.fuel.rod": " :poᴚ ןǝnℲ", "createnuclear.tooltip.item.unknown.rod": " :uʍouʞu∩", - "createnuclear.tooltip.item.uranium.rod": " :poᴚ ɯnıuɐɹ∩", + "createnuclear.tooltip.proximityRodHeat": "Ὁ ɟᄅ˙% :ʇɐǝH poᴚ ʎʇıɯıxoɹԀ", + "createnuclear.tooltip.ratio": "%d :oıʇɐɹ ɹoɟ ǝnןɐΛ poᴚ", + "createnuclear.tooltip.rodTimer": "ʞɔıʇ %d :uoıʇɐɹnᗡ poᴚ", + "createnuclear.tooltip.statRod": ":uɹǝʇʇɐԀ ʇɐʇS poᴚ", + "createnuclear.tooltip.typeRod": "%s :ǝdʎ⟘ poᴚ", + "death.attack.createnuclear.fan_radiation": "ʇsɐןq uoıʇɐıpɐɹ ɯoɹɟ pǝıp %1$s", + "death.attack.createnuclear.radiation": "uoıʇɐıpɐɹ ɯoɹɟ pǝıp %1$s", + "effect.createnuclear.iodine": "ǝuıpoI", "effect.createnuclear.radiation": "uoıʇɐıpɐᴚ", "emi.category.createnuclear.fan_enriched": "buıɥɔıɹuƎ ʞןnᗺ", + "emi.category.createnuclear.snow_powder": "uɐɟ ɔıuǝboʎɹƆ", "entity.createnuclear.irradiated_cat": "ʇɐƆ pǝʇɐıpɐɹɹI", "entity.createnuclear.irradiated_chicken": "uǝʞɔıɥƆ pǝʇɐıpɐɹɹI", + "entity.createnuclear.irradiated_cow": "ʍoƆ pǝʇɐıpɐɹɹI", "entity.createnuclear.irradiated_wolf": "ɟןoM pǝʇɐıpɐɹɹI", + "entity.createnuclear.nuclear_explosion": "uoısoןdxƎ ɹɐǝןɔnN", + "fluid.createnuclear.nitrogen": "uǝboɹʇıN pınbıꞀ", + "fluid.createnuclear.thorium": "ɯnıɹoɥ⟘ pınbıꞀ", "fluid.createnuclear.uranium": "ɯnıuɐɹ∩ pınbıꞀ", "gui.createnuclear.reactor_controller.title": "ɹǝןןoɹʇuoƆ ɹoʇɔɐǝᴚ", "gui.createnuclear.reactor_input.title": "ǝbɐɹoʇS ʇnduI ɹoʇɔɐǝᴚ", - "item.createnuclear.anti_radiation_boots": "sʇooᗺ uoıʇɐıpɐᴚ ıʇuⱯ", - "item.createnuclear.black_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ʞɔɐןᗺ", - "item.createnuclear.black_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ʞɔɐןᗺ", - "item.createnuclear.black_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ʞɔɐןᗺ", + "irradiated.taming.wip": "ssǝɹboɹd uı ʞɹoʍ ɐ ןןıʇs ǝɹɐ sqoɯ pǝʇɐıpɐɹɹı - ʇǝʎ pǝɯɐʇ ǝq ʇouuɐɔ ǝɹnʇɐǝɹɔ sıɥ⟘", + "item.createnuclear.biome_irradiation_extractor": "ɹoʇɔɐɹʇxƎ uoıʇɐıpɐɹɹI ǝɯoıᗺ", "item.createnuclear.black_cloth": "ɥʇoןƆ ʞɔɐןᗺ", - "item.createnuclear.blue_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ǝnןᗺ", - "item.createnuclear.blue_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ǝnןᗺ", - "item.createnuclear.blue_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ǝnןᗺ", "item.createnuclear.blue_cloth": "ɥʇoןƆ ǝnןᗺ", - "item.createnuclear.brown_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ uʍoɹᗺ", - "item.createnuclear.brown_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ uʍoɹᗺ", - "item.createnuclear.brown_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ uʍoɹᗺ", "item.createnuclear.brown_cloth": "ɥʇoןƆ uʍoɹᗺ", "item.createnuclear.cat_irradiated_spawn_egg": "bbƎ uʍɐdS ʇɐƆ pǝʇɐıpɐɹɹI", "item.createnuclear.chicken_irradiated_spawn_egg": "bbƎ uʍɐdS uǝʞɔıɥƆ pǝʇɐıpɐɹɹI", "item.createnuclear.coal_dust": "ʇsnᗡ ןɐoƆ", - "item.createnuclear.cyan_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ uɐʎƆ", - "item.createnuclear.cyan_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ uɐʎƆ", - "item.createnuclear.cyan_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ uɐʎƆ", + "item.createnuclear.cooled_nitrogen_concentrate": "ǝʇɐɹʇuǝɔuoƆ uǝboɹʇıN pǝןooƆ", "item.createnuclear.cyan_cloth": "ɥʇoןƆ uɐʎƆ", + "item.createnuclear.default_anti_radiation_boots": "sʇooᗺ uoıʇɐıpɐᴚ ıʇuⱯ", + "item.createnuclear.default_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ", + "item.createnuclear.default_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ", + "item.createnuclear.default_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ", "item.createnuclear.enriched_yellowcake": "ǝʞɐɔʍoןןǝʎ pǝɥɔıɹuƎ", "item.createnuclear.graphene": "ǝuǝɥdɐɹ⅁", "item.createnuclear.graphite_rod": "poᴚ ǝʇıɥdɐɹ⅁", "item.createnuclear.graphite_rod.tooltip.summary": "˙ʇı ǝʇɐɹǝdo oʇ ‾ʇnduı ɹoʇɔɐǝɹ‾ ǝɥʇ uı pǝsn ǝq oʇ ‾ʞɔıʇS‾", - "item.createnuclear.gray_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ʎɐɹ⅁", - "item.createnuclear.gray_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ʎɐɹ⅁", - "item.createnuclear.gray_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ʎɐɹ⅁", "item.createnuclear.gray_cloth": "ɥʇoןƆ ʎɐɹ⅁", - "item.createnuclear.green_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ uǝǝɹ⅁", - "item.createnuclear.green_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ uǝǝɹ⅁", - "item.createnuclear.green_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ uǝǝɹ⅁", "item.createnuclear.green_cloth": "ɥʇoןƆ uǝǝɹ⅁", "item.createnuclear.lead_ingot": "ʇobuI pɐǝꞀ", "item.createnuclear.lead_nugget": "ʇǝbbnN pɐǝꞀ", - "item.createnuclear.light_blue_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ǝnןᗺ ʇɥbıꞀ", - "item.createnuclear.light_blue_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ǝnןᗺ ʇɥbıꞀ", - "item.createnuclear.light_blue_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ǝnןᗺ ʇɥbıꞀ", "item.createnuclear.light_blue_cloth": "ɥʇoןƆ ǝnןᗺ ʇɥbıꞀ", - "item.createnuclear.light_gray_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ʎɐɹ⅁ ʇɥbıꞀ", - "item.createnuclear.light_gray_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ʎɐɹ⅁ ʇɥbıꞀ", - "item.createnuclear.light_gray_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ʎɐɹ⅁ ʇɥbıꞀ", "item.createnuclear.light_gray_cloth": "ɥʇoןƆ ʎɐɹ⅁ ʇɥbıꞀ", - "item.createnuclear.lime_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ǝɯıꞀ", - "item.createnuclear.lime_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ǝɯıꞀ", - "item.createnuclear.lime_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ǝɯıꞀ", "item.createnuclear.lime_cloth": "ɥʇoןƆ ǝɯıꞀ", - "item.createnuclear.magenta_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ɐʇuǝbɐW", - "item.createnuclear.magenta_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ɐʇuǝbɐW", - "item.createnuclear.magenta_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ɐʇuǝbɐW", "item.createnuclear.magenta_cloth": "ɥʇoןƆ ɐʇuǝbɐW", - "item.createnuclear.orange_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ǝbuɐɹO", - "item.createnuclear.orange_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ǝbuɐɹO", - "item.createnuclear.orange_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ǝbuɐɹO", + "item.createnuclear.nitrate": "ǝʇɐɹʇıN", + "item.createnuclear.nitrogen_bucket": "ʇǝʞɔnᗺ uǝboɹʇıN", + "item.createnuclear.nitrogen_concentrate": "ǝʇɐɹʇuǝɔuoƆ uǝboɹʇıN", "item.createnuclear.orange_cloth": "ɥʇoןƆ ǝbuɐɹO", - "item.createnuclear.pink_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ʞuıԀ", - "item.createnuclear.pink_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ʞuıԀ", - "item.createnuclear.pink_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ʞuıԀ", "item.createnuclear.pink_cloth": "ɥʇoןƆ ʞuıԀ", - "item.createnuclear.purple_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ǝןdɹnԀ", - "item.createnuclear.purple_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ǝןdɹnԀ", - "item.createnuclear.purple_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ǝןdɹnԀ", "item.createnuclear.purple_cloth": "ɥʇoןƆ ǝןdɹnԀ", "item.createnuclear.raw_lead": "pɐǝꞀ ʍɐᴚ", + "item.createnuclear.raw_thorium": "ɯnıɹoɥ⟘ ʍɐᴚ", "item.createnuclear.raw_uranium": "ɯnıuɐɹ∩ ʍɐᴚ", + "item.createnuclear.reactor_blueprint.chat_info": ":uoıʇɐʇuǝɯnɔop ǝɥʇ uǝdo oʇ ʞuıן ǝɥʇ ʍoןןoℲ", + "item.createnuclear.reactor_blueprint.tooltip": "˙ʇnoʎɐן ɹoıɹǝʇuı s,ɹoʇɔɐǝɹ ǝɥʇ ǝzıןɐnsıʌ puɐ ubısǝp oʇ pǝs∩", + "item.createnuclear.reactor_blueprint.tooltip_hint": "˙ʞuıן ıʞıM ǝɥʇ ʇǝb oʇ puɐɥ uı ʇuıɹdǝnןq ǝɥʇ ɥʇıʍ oʇㄥ§ ʞɔıןƆ ʇɥbıᴚ + ʇɟıɥSǝ§ ssǝɹԀㄥ§", + "item.createnuclear.reactor_blueprint.wiki_link": "]ıʞıM ןɐıɔıɟɟO uǝdO[", "item.createnuclear.reactor_blueprint_item": "ʇuıɹdǝnןᗺ ɹoʇɔɐǝᴚ", "item.createnuclear.reactor_blueprint_item.tooltip.behaviour1": "˙ʇı ןןıɟ oʇ ʞɔıןɔ ‾ʇɥbıᴚ‾", "item.createnuclear.reactor_blueprint_item.tooltip.behaviour2": "˙ʇı uǝdo oʇ ɹǝןןoɹʇuoɔ ɹoʇɔɐǝɹ ǝɥʇ uo ʞɔıןɔ ‾ʇɥbıᴚ‾", - "item.createnuclear.reactor_blueprint_item.tooltip.condition1": "spoɹ ɯnıuɐɹn puɐ ǝʇıɥdɐɹb ɥʇıʍ pǝןןıℲ", + "item.createnuclear.reactor_blueprint_item.tooltip.condition1": "spoɹ ןǝnɟ puɐ buıןooɔ ɥʇıʍ pǝןןıℲ", "item.createnuclear.reactor_blueprint_item.tooltip.condition2": "pǝןqɯǝssɐ ǝq ʇsnɯ ɹoʇɔɐǝɹ ǝɥ⟘", "item.createnuclear.reactor_blueprint_item.tooltip.summary": "˙uɹǝʇʇɐd uʍo ɹnoʎ ǝɹnbıɟuoɔ oʇ noʎ sʍoןןɐ ʇI", - "item.createnuclear.red_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ pǝᴚ", - "item.createnuclear.red_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ pǝᴚ", - "item.createnuclear.red_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ pǝᴚ", "item.createnuclear.red_cloth": "ɥʇoןƆ pǝᴚ", + "item.createnuclear.reinforced_glass_bottle": "ǝןʇʇoᗺ ssɐן⅁ pǝɔɹoɟuıǝᴚ", "item.createnuclear.steel_ingot": "ʇobuI ןǝǝʇS", "item.createnuclear.steel_nugget": "ʇǝbbnN ןǝǝʇS", + "item.createnuclear.thorium_bucket": "ʇǝʞɔnᗺ ɯnıɹoɥ⟘", + "item.createnuclear.thorium_dust": "ʇsnᗡ ɯnıɹoɥ⟘", + "item.createnuclear.thorium_ingot": "ʇobuI ɯnıɹoɥ⟘", + "item.createnuclear.thorium_nugget": "ʇǝbbnN ɯnıɹoɥ⟘", + "item.createnuclear.thorium_rod": "poᴚ ɯnıɹoɥ⟘", "item.createnuclear.uranium_bucket": "ʇǝʞɔnᗺ ɯnıuɐɹ∩", "item.createnuclear.uranium_powder": "ɹǝpʍoԀ ɯnıuɐɹ∩", "item.createnuclear.uranium_rod": "poᴚ ɯnıuɐɹ∩", "item.createnuclear.uranium_rod.tooltip.summary": "˙ʇı ǝʇɐɹǝdo oʇ ‾ʇnduı ɹoʇɔɐǝɹ‾ ǝɥʇ uı pǝsn ǝq oʇ ‾ʞɔıʇS‾", - "item.createnuclear.white_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ǝʇıɥM", - "item.createnuclear.white_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ǝʇıɥM", - "item.createnuclear.white_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ǝʇıɥM", "item.createnuclear.white_cloth": "ɥʇoןƆ ǝʇıɥM", "item.createnuclear.wolf_irradiated_spawn_egg": "bbƎ uʍɐdS ɟןoM pǝʇɐıpɐɹɹI", - "item.createnuclear.yellow_anti_radiation_chestplate": "ǝʇɐןdʇsǝɥƆ uoıʇɐıpɐᴚ ıʇuⱯ ʍoןןǝʎ", - "item.createnuclear.yellow_anti_radiation_helmet": "ʇǝɯןǝH uoıʇɐıpɐᴚ ıʇuⱯ ʍoןןǝʎ", - "item.createnuclear.yellow_anti_radiation_leggings": "sbuıbbǝꞀ uoıʇɐıpɐᴚ ıʇuⱯ ʍoןןǝʎ", "item.createnuclear.yellow_cloth": "ɥʇoןƆ ʍoןןǝʎ", "item.createnuclear.yellowcake": "ǝʞɐɔʍoןןǝʎ", + "item.minecraft.lingering_potion.effect.potion_of_iodine": "ǝuıpoI ɟo uoıʇoԀ buıɹǝbuıꞀ", + "item.minecraft.lingering_potion.effect.potion_of_iodine_augment": "ǝuıpoI ɟo uoıʇoԀ buıɹǝbuıꞀ", "item.minecraft.lingering_potion.effect.potion_of_radiation_1": "uoıʇɐıpɐᴚ ɟo uoıʇoԀ buıɹǝbuıꞀ", "item.minecraft.lingering_potion.effect.potion_of_radiation_2": "uoıʇɐıpɐᴚ ɟo uoıʇoԀ buıɹǝbuıꞀ", "item.minecraft.lingering_potion.effect.potion_of_radiation_augment_1": "uoıʇɐıpɐᴚ ɟo uoıʇoԀ buıɹǝbuıꞀ", + "item.minecraft.potion.effect.potion_of_iodine": "ǝuıpoI ɟo uoıʇoԀ", + "item.minecraft.potion.effect.potion_of_iodine_augment": "ǝuıpoI ɟo uoıʇoԀ", "item.minecraft.potion.effect.potion_of_radiation_1": "uoıʇɐıpɐᴚ ɟo uoıʇoԀ", "item.minecraft.potion.effect.potion_of_radiation_2": "uoıʇɐıpɐᴚ ɟo uoıʇoԀ", "item.minecraft.potion.effect.potion_of_radiation_augment_1": "uoıʇɐıpɐᴚ ɟo uoıʇoԀ", + "item.minecraft.splash_potion.effect.potion_of_iodine": "ǝuıpoI ɟo uoıʇoԀ ɥsɐןdS", + "item.minecraft.splash_potion.effect.potion_of_iodine_augment": "ǝuıpoI ɟo uoıʇoԀ ɥsɐןdS", "item.minecraft.splash_potion.effect.potion_of_radiation_1": "uoıʇɐıpɐᴚ ɟo uoıʇoԀ ɥsɐןdS", "item.minecraft.splash_potion.effect.potion_of_radiation_2": "uoıʇɐıpɐᴚ ɟo uoıʇoԀ ɥsɐןdS", "item.minecraft.splash_potion.effect.potion_of_radiation_augment_1": "uoıʇɐıpɐᴚ ɟo uoıʇoԀ ɥsɐןdS", + "item.minecraft.tipped_arrow.effect.potion_of_iodine": "ǝuıpoI ɟo ʍoɹɹⱯ", + "item.minecraft.tipped_arrow.effect.potion_of_iodine_augment": "ǝuıpoI ɟo ʍoɹɹⱯ", "item.minecraft.tipped_arrow.effect.potion_of_radiation_1": "uoıʇɐıpɐᴚ ɟo ʍoɹɹⱯ", "item.minecraft.tipped_arrow.effect.potion_of_radiation_2": "uoıʇɐıpɐᴚ ɟo ʍoɹɹⱯ", "item.minecraft.tipped_arrow.effect.potion_of_radiation_augment_1": "uoıʇɐıpɐᴚ ɟo ʍoɹɹⱯ", diff --git a/src/generated/resources/assets/createnuclear/lang/en_us.json b/src/generated/resources/assets/createnuclear/lang/en_us.json index 2aefa36..565a4d2 100644 --- a/src/generated/resources/assets/createnuclear/lang/en_us.json +++ b/src/generated/resources/assets/createnuclear/lang/en_us.json @@ -1,24 +1,46 @@ { - "advancement.createnuclear.anti_radiation_armor": "Anti radiation Armor", + "advancement.createnuclear.absolute_zero": "Absolute Zero", + "advancement.createnuclear.absolute_zero.desc": "Mix cooled nitrogen concentrate to obtain liquid nitrogen", + "advancement.createnuclear.anti_radiation_armor": "Anti Radiation Armor", "advancement.createnuclear.anti_radiation_armor.desc": "Craft your first anti-radiation armor piece to protect yourself from radiation", "advancement.createnuclear.automatic_uranium": "Automating Uranium", "advancement.createnuclear.automatic_uranium.desc": "Obtain some uranium powder using the automatic uranium processing\n§7(Hidden Advancement)", + "advancement.createnuclear.avoiding_cancer": "Best Keep Yourself Covered", + "advancement.createnuclear.avoiding_cancer.desc": "Equip anti-radiation armor for the first time", + "advancement.createnuclear.chemistry_101": "Crushing It", + "advancement.createnuclear.chemistry_101.desc": "Mine nitrate ore or crush limestone to obtain nitrate", + "advancement.createnuclear.chill_out": "Chill Out", + "advancement.createnuclear.chill_out.desc": "Cool down nitrogen concentrate to prepare it for liquefaction", "advancement.createnuclear.coal_dust": "Coal Dust", "advancement.createnuclear.coal_dust.desc": "Crush coal or charcoal to obtain coal dust, a key crafting material", + "advancement.createnuclear.craft_enriching_campfire": "Does That Make Smoke?", + "advancement.createnuclear.craft_enriching_campfire.desc": "Craft an Enriching Campfire", + "advancement.createnuclear.crunchy_uranium": "What Did You Expect", + "advancement.createnuclear.crunchy_uranium.desc": "Bro..... you did what ??\n§7(Hidden Advancement)", + "advancement.createnuclear.cryogenic_baptism": "I can't Feel My Feet Anymore", + "advancement.createnuclear.cryogenic_baptism.desc": "Swim in the liquid nitrogen for the first time\n§7(Hidden Advancement)", "advancement.createnuclear.dye_anti_radiation_armor": "Pimp My Armor", "advancement.createnuclear.dye_anti_radiation_armor.desc": "Dye your anti radiation armor to any color", "advancement.createnuclear.enriched_yellowcake": "Enhancing Yellowcake", "advancement.createnuclear.enriched_yellowcake.desc": "Use a fan to enrich yellowcake and make it more powerful", - "advancement.createnuclear.full_anti_radiation_armor": "Fully Protected", - "advancement.createnuclear.full_anti_radiation_armor.desc": "Wear a full set of anti-radiation armor to fully protect yourself from radiation", + "advancement.createnuclear.feeding_the_reactor": "Feeding The Reactor", + "advancement.createnuclear.feeding_the_reactor.desc": "Craft a Reactor Rod Input to feed heating and cooling rods into your reactor", + "advancement.createnuclear.fueling_the_reactor": "Fueling The Reactor", + "advancement.createnuclear.fueling_the_reactor.desc": "Craft a Reactor Fluid Input to feed liquid coolant into your reactor", + "advancement.createnuclear.getting_concentrated": "Getting Concentrated", + "advancement.createnuclear.getting_concentrated.desc": "Smelt nitrate in a blast furnace to obtain nitrogen concentrate", "advancement.createnuclear.graphene": "Graphene", "advancement.createnuclear.graphene.desc": "Press coal dust to create graphene", "advancement.createnuclear.graphite_rod": "Don't Forget Those Ones", "advancement.createnuclear.graphite_rod.desc": "Combine graphene and steel ingots in a mechanical crafter to make graphite rods", - "advancement.createnuclear.lead_ingot": "Lead ingot", + "advancement.createnuclear.lead_ingot": "Lead Ingot", "advancement.createnuclear.lead_ingot.desc": "Smelt a raw lead to obtain a lead ingot", + "advancement.createnuclear.no_time_to_die": "No Time To Die", + "advancement.createnuclear.no_time_to_die.desc": "Stop the reactor before the KABOOOM !", "advancement.createnuclear.raw_lead": "Raw Lead", "advancement.createnuclear.raw_lead.desc": "Obtain some raw lead by mining lead ore", + "advancement.createnuclear.raw_thorium": "Thorium's Glow", + "advancement.createnuclear.raw_thorium.desc": "Mine thorium ore to obtain raw thorium for further processing", "advancement.createnuclear.raw_uranium": "The Raw Power", "advancement.createnuclear.raw_uranium.desc": "Mine uranium ore to obtain raw uranium for further processing", "advancement.createnuclear.reactor_blueprint": "Blueprint For Power", @@ -29,20 +51,34 @@ "advancement.createnuclear.reactor_controller.desc": "Craft a reactor controller to manage and regulate your reactor", "advancement.createnuclear.reactor_cooler": "Cooling The Reactor", "advancement.createnuclear.reactor_cooler.desc": "Craft a reactor cooler to cool your reactor", - "advancement.createnuclear.reactor_core": "Core of Power", + "advancement.createnuclear.reactor_core": "Core Of Power", "advancement.createnuclear.reactor_core.desc": "Craft the reactor core to harness the full energy of your nuclear reactor", "advancement.createnuclear.reactor_frame": "Reactor Frame", "advancement.createnuclear.reactor_frame.desc": "Craft a reactor frame to build your nuclear reactor", - "advancement.createnuclear.reactor_input": "Fueling The Reactor", - "advancement.createnuclear.reactor_input.desc": "Craft a reactor input to feed uranium and graphite rods into your reactor", - "advancement.createnuclear.reactor_output": "Power Output", - "advancement.createnuclear.reactor_output.desc": "Craft a reactor output to transfer the energy produced by your reactor", "advancement.createnuclear.reinforced_glass": "Reinforced Glass", "advancement.createnuclear.reinforced_glass.desc": "Craft some reinforced glass for the first time", "advancement.createnuclear.root": "Starting The Nuclear Journey", "advancement.createnuclear.root.desc": "Unlock the basics of nuclear energy and get your first uranium powder", + "advancement.createnuclear.silence_the_core": "It Makes So Much Noise !", + "advancement.createnuclear.silence_the_core.desc": "sound the alarm for the first time", "advancement.createnuclear.steel_ingot": "Steel Ingot", "advancement.createnuclear.steel_ingot.desc": "Combine coal dust and iron ingots to create steel ingots", + "advancement.createnuclear.t1": "Reactor Controller T1", + "advancement.createnuclear.t1.desc": "Build a tier 1 Nuclear Reactor", + "advancement.createnuclear.t2": "Reactor Controller T2", + "advancement.createnuclear.t2.desc": "Build a tier 2 Nuclear Reactor", + "advancement.createnuclear.t3": "Reactor Controller T3", + "advancement.createnuclear.t3.desc": "Build a tier 3 Nuclear Reactor", + "advancement.createnuclear.thorium_dust": "Powdered Thorium", + "advancement.createnuclear.thorium_dust.desc": "Crush raw thorium into dust to prepare for further refining", + "advancement.createnuclear.thorium_ingot": "Compacted Thorium", + "advancement.createnuclear.thorium_ingot.desc": "Compact thorium liquid to create a thorium ingot", + "advancement.createnuclear.thorium_liquid": "Molten Thorium", + "advancement.createnuclear.thorium_liquid.desc": "Obtain some thorium liquid by mixing thorium dust", + "advancement.createnuclear.thorium_rod": "What A Blue Stick", + "advancement.createnuclear.thorium_rod.desc": "Craft a thorium rod for the first time", + "advancement.createnuclear.unlimited_power": "Unlimited Power", + "advancement.createnuclear.unlimited_power.desc": "Craft a Reactor Output to extract the energy produced by your reactor", "advancement.createnuclear.uranium_liquid": "Turning Solid To Liquid", "advancement.createnuclear.uranium_liquid.desc": "Obtain some uranium liquid by mixing uranium powder", "advancement.createnuclear.uranium_powder": "Powdered Uranium", @@ -51,6 +87,7 @@ "advancement.createnuclear.uranium_rod.desc": "Create your first uranium rod using enriched yellowcake in a mechanical crafter", "advancement.createnuclear.yellowcake": "The Yellowcake Process", "advancement.createnuclear.yellowcake.desc": "Compact uranium liquid to create yellowcake", + "attribute.name.createnuclear.generic.irradiated_resistance": "Radiation Resistance", "block.createnuclear.autunite": "Autunite", "block.createnuclear.autunite_pillar": "Autunite Pillar", "block.createnuclear.cut_autunite": "Cut Autunite", @@ -62,6 +99,8 @@ "block.createnuclear.cut_autunite_stairs": "Cut Autunite Stairs", "block.createnuclear.cut_autunite_wall": "Cut Autunite Wall", "block.createnuclear.deepslate_lead_ore": "Deepslate Lead Ore", + "block.createnuclear.deepslate_nitrate_ore": "Deepslate Nitrate Ore", + "block.createnuclear.deepslate_thorium_ore": "Deepslate Thorium Ore", "block.createnuclear.deepslate_uranium_ore": "Deepslate Uranium Ore", "block.createnuclear.enriched_soul_soil": "Enriched Soul Soil", "block.createnuclear.enriched_soul_soil.tooltip.summary": "The _only_ block who create _enriched fire_.Can be used to _craft_ enriched campfire or just to make a _green fire_.", @@ -70,12 +109,16 @@ "block.createnuclear.layered_autunite": "Layered Autunite", "block.createnuclear.lead_block": "Lead Block", "block.createnuclear.lead_ore": "Lead Ore", + "block.createnuclear.nitrate_ore": "Nitrate Ore", + "block.createnuclear.nitrogen": "Nitrogen", "block.createnuclear.polished_cut_autunite": "Polished Cut Autunite", "block.createnuclear.polished_cut_autunite_slab": "Polished Cut Autunite Slab", "block.createnuclear.polished_cut_autunite_stairs": "Polished Cut Autunite Stairs", "block.createnuclear.polished_cut_autunite_wall": "Polished Cut Autunite Wall", "block.createnuclear.raw_lead_block": "Raw Lead Block", + "block.createnuclear.raw_thorium_block": "Raw Thorium Block", "block.createnuclear.raw_uranium_block": "Raw Uranium Block", + "block.createnuclear.reactor_alarm": "Reactor Alarm", "block.createnuclear.reactor_casing": "Reactor Casing", "block.createnuclear.reactor_casing.tooltip.summary": "_Block_ used to build the _reactor_", "block.createnuclear.reactor_controller": "Reactor Controller", @@ -86,9 +129,12 @@ "block.createnuclear.reactor_cooler.tooltip.summary": "_Block_ used to build the _reactor_", "block.createnuclear.reactor_core": "Reactor Core", "block.createnuclear.reactor_core.tooltip.summary": "_Block_ used to build the _reactor_", + "block.createnuclear.reactor_fluid_input": "Reactor Fluid Input", + "block.createnuclear.reactor_fluid_input.tooltip.behaviour1": "Insert _Water_ or _Liquid Nitrogen_ in large quantities to power _The Reactor_ and avoid _overheating_.", + "block.createnuclear.reactor_fluid_input.tooltip.condition1": "When the reactor is assembled", + "block.createnuclear.reactor_fluid_input.tooltip.summary": "_The Reactor Fluid Input_ is a _block_ that can be used to insert _Water_ or _Liquid Nitrogen_ into the Reactor.", "block.createnuclear.reactor_frame": "Reactor Frame", "block.createnuclear.reactor_frame.tooltip.summary": "_Block_ used to build the _reactor_", - "block.createnuclear.reactor_input": "Reactor Input", "block.createnuclear.reactor_input.tooltip.behaviour1": "Insert _uranium_ and _graphene_ rods in large quantities to power _the reactor_ ", "block.createnuclear.reactor_input.tooltip.condition1": "When the Reactor is assembled", "block.createnuclear.reactor_input.tooltip.summary": "_The Reactor Input_ is a _block_ that can be used to insert _Uranium_ and _Graphene_ rods into the _Reactor_", @@ -96,147 +142,268 @@ "block.createnuclear.reactor_output.tooltip.behaviour1": "You can _extract the energy_ produce by the reactor by attaching _shaft_ to the _reactor output_", "block.createnuclear.reactor_output.tooltip.condition1": "When the reactor produce energy", "block.createnuclear.reactor_output.tooltip.summary": "_The Reactor Output_ is a _block_ that can be used to extract the mechanical energy generated by the _Reactor_", + "block.createnuclear.reactor_rod_input": "Reactor Rod Input", "block.createnuclear.reinforced_glass": "Reinforced Glass", "block.createnuclear.small_autunite_brick_slab": "Small Autunite Brick Slab", "block.createnuclear.small_autunite_brick_stairs": "Small Autunite Brick Stairs", "block.createnuclear.small_autunite_brick_wall": "Small Autunite Brick Wall", "block.createnuclear.small_autunite_bricks": "Small Autunite Bricks", "block.createnuclear.steel_block": "Steel Block", + "block.createnuclear.thorium": "Thorium", + "block.createnuclear.thorium_block": "Thorium Block", + "block.createnuclear.thorium_ore": "Thorium Ore", "block.createnuclear.uranium": "Uranium", "block.createnuclear.uranium_ore": "Uranium Ore", "create.recipe.fan_enriched.fan": "Fan behind Enriched Fire", + "create.recipe.fan_snow_powder.fan": "Fan behind Powder Snow", + "createnuclear.display_source.cooler": "Reactor Cooler", + "createnuclear.display_source.fuel": "Reactor Fuel", + "createnuclear.display_source.heat": "Reactor Heat", + "createnuclear.display_source.heat.rotation": "RPM", + "createnuclear.display_source.heat.type": "Heat level", + "createnuclear.display_source.heat.value": "Q", + "createnuclear.display_source.liquid": "Liquid Level", + "createnuclear.display_source.liquid_level": "Reactor Liquid Level", + "createnuclear.display_source.reactor.active": "ACTIVE", + "createnuclear.display_source.reactor.cooler": "Cooler: ", + "createnuclear.display_source.reactor.fluid": "Fluid: ", + "createnuclear.display_source.reactor.for_reactor_status": "for reactor status", + "createnuclear.display_source.reactor.fuel": "Fuel: ", + "createnuclear.display_source.reactor.heat": "Heat: ", + "createnuclear.display_source.reactor.idle": "IDLE", + "createnuclear.display_source.reactor.mode.gauge": "Gauges", + "createnuclear.display_source.reactor.mode.normal": "Normal", + "createnuclear.display_source.reactor.mode.percent": "Percentages", + "createnuclear.display_source.reactor.mode.value": "Values", + "createnuclear.display_source.reactor.no_controller": "No Reactor Controller found", + "createnuclear.display_source.reactor.not_enough_space": "Not enough space ", + "createnuclear.display_source.reactor.size": "Tier: ", + "createnuclear.display_source.reactor.size.large": "Large", + "createnuclear.display_source.reactor.size.medium": "Medium", + "createnuclear.display_source.reactor.size.small": "Small", + "createnuclear.display_source.reactor.status": "Status: ", + "createnuclear.display_source.reactor_controller_count_rod.cooled": "Cooled", + "createnuclear.display_source.reactor_controller_count_rod.fuel": "Fuel", + "createnuclear.display_source.reactor_count_rod": "Count Rod in Pattern", + "createnuclear.display_source.reactor_summary": "Reactor Summary", + "createnuclear.display_source.reactor_summary.active": "ACTIVE", + "createnuclear.display_source.reactor_summary.coolant": "Coolant:", + "createnuclear.display_source.reactor_summary.fuel": "Rods:", + "createnuclear.display_source.reactor_summary.idle": "IDLE", + "createnuclear.display_source.reactor_summary.no_controller": "Reactor not found", + "createnuclear.display_source.reactor_summary.status": "Status:", + "createnuclear.display_source.reactor_summary.temperature": "Temp:", + "createnuclear.display_source.size": "Reactor Size", "createnuclear.enriched.fan.recipe": "Bulk Enriching", + "createnuclear.generic.unit.count.rod": "Counts %s Rod", + "createnuclear.generic.unit.countCooled.rod": "Count Cooled Rod: %d", + "createnuclear.generic.unit.countFuel.rod": "Count Fuel Rod: %d", + "createnuclear.generic.unit.fluid.value": "mB", "createnuclear.generic.unit.heat": "Q", + "createnuclear.generic.unit.heat.rotation": "RPM", + "createnuclear.generic.unit.heat.type": "Heat Level: %s", + "createnuclear.generic.unit.heat.value": "Q", + "createnuclear.generic.unit.liquid": "WIP", + "createnuclear.generic.unit.seconds": "s", "createnuclear.gui.reactor_controller.info_header.title": "Heat value", - "createnuclear.ponder.reactor.header": "Construction of the reactor", - "createnuclear.ponder.reactor.text_1": "Floor 1", - "createnuclear.ponder.reactor.text_10": "Floor 7", - "createnuclear.ponder.reactor.text_2": "Reactor Output: This is the block that outputs the energy (SU) generated by the reactor.", - "createnuclear.ponder.reactor.text_3": "Floor 2", - "createnuclear.ponder.reactor.text_4": "Floor 3", - "createnuclear.ponder.reactor.text_5": "Floor 4", - "createnuclear.ponder.reactor.text_6": "Reactor Input: A block that stores uranium and graphite rods to operate the reactor.", - "createnuclear.ponder.reactor.text_7": "Reactor Controller: The most important block to operate the reactor; it handles all the calculations needed to generate power.", - "createnuclear.ponder.reactor.text_8": "Floor 5", - "createnuclear.ponder.reactor.text_9": "Floor 6", - "createnuclear.ponder.reactor_blueprint.header": "Controller Activation", - "createnuclear.ponder.reactor_blueprint.text_1": "Reactor Blueprint: the most important element; it allows the reactor to be configured according to specific models.", + "createnuclear.notification.reactor.assembled": "Reactor has been assembled", + "createnuclear.notification.reactor.critical_failure": "CRITICAL FAILURE", + "createnuclear.notification.reactor.destroyed": "REACTOR DESTROYED", + "createnuclear.notification.reactor.disassembled": "Reactor has been disassembled", + "createnuclear.notification.reactor.imminent_explosion": "IMMINENT EXPLOSION", + "createnuclear.notification.reactor.meltdown_finished": "Critical meltdown completed", + "createnuclear.notification.reactor.meltdown_in": "CORE MELTDOWN IN ", + "createnuclear.notification.reactor.overheating": "WARNING: CORE OVERHEATING", + "createnuclear.notification.reactor.stabilized": "CORE STABILIZED", + "createnuclear.ponder.reactor_io_placement.header": "Reactor I/O: Function & Placement", + "createnuclear.ponder.reactor_io_placement.text_1": "Rod Input: Stores Heating or Cooling Rods. We need one Heating Rod (fuel) to heat the reactor, and one Cooling Rod for stability.", + "createnuclear.ponder.reactor_io_placement.text_2": "Second Rod Input: This is why we need at least two inputs! One for the Heating Rod and one for the Cooling Rod to prevent explosions.", + "createnuclear.ponder.reactor_io_placement.text_3": "Fluid Input: Fluid is also required to cool the reactor and ensure it does not explode.", + "createnuclear.ponder.reactor_io_placement.text_4": "Alarm (Optional): Emits a sound when the reactor becomes unstable and risks exploding.", + "createnuclear.ponder.reactor_io_placement.text_5": "Output: Necessary to extract generated energy. You can place multiple outputs to dispatch the total energy between them.", + "createnuclear.ponder.reactor_io_placement.text_6": "These blocks can replace ANY Reactor Casing, as long as it is not on an edge.", + "createnuclear.ponder.reactor_io_placement.text_7": "They can be grouped together on the roof or any other flat surface.", + "createnuclear.ponder.reactor_t1.header": "Reactor T1", + "createnuclear.ponder.reactor_t1.text_1": "Floor 1", + "createnuclear.ponder.reactor_t1.text_10": "Note: Check page 4 for I/O and Alarm blocks (placement & function).", + "createnuclear.ponder.reactor_t1.text_2": "Floor 2", + "createnuclear.ponder.reactor_t1.text_3": "Floor 3", + "createnuclear.ponder.reactor_t1.text_4": "Floor 4", + "createnuclear.ponder.reactor_t1.text_5": "Controller: brain of the reactor, and the place where the blueprint goes to start it", + "createnuclear.ponder.reactor_t1.text_6": "Floor 5", + "createnuclear.ponder.reactor_t1.text_7": "Floor 6", + "createnuclear.ponder.reactor_t1.text_8": "Floor 7", + "createnuclear.ponder.reactor_t1.text_9": "To start the reactor you will need liquid and rods corresponding to the pattern, then right click the controller with the blueprint in hand", + "createnuclear.ponder.reactor_t2.header": "Reactor T2", + "createnuclear.ponder.reactor_t2.text_1": "Floor 1", + "createnuclear.ponder.reactor_t2.text_10": "Floor 9", + "createnuclear.ponder.reactor_t2.text_11": "To start the reactor you will need liquid and rods corresponding to the pattern, then right click the controller with the blueprint in hand", + "createnuclear.ponder.reactor_t2.text_12": "Note: Check page 4 for I/O and Alarm blocks (placement & function).", + "createnuclear.ponder.reactor_t2.text_2": "Floor 2", + "createnuclear.ponder.reactor_t2.text_3": "Floor 3", + "createnuclear.ponder.reactor_t2.text_4": "Floor 4", + "createnuclear.ponder.reactor_t2.text_5": "Floor 5", + "createnuclear.ponder.reactor_t2.text_6": "Controller: brain of the reactor, and the place where the blueprint goes to start it", + "createnuclear.ponder.reactor_t2.text_7": "Floor 6", + "createnuclear.ponder.reactor_t2.text_8": "Floor 7", + "createnuclear.ponder.reactor_t2.text_9": "Floor 8", + "createnuclear.ponder.reactor_t3.header": "Reactor T3", + "createnuclear.ponder.reactor_t3.text_1": "Floor 1", + "createnuclear.ponder.reactor_t3.text_10": "Floor 9", + "createnuclear.ponder.reactor_t3.text_11": "Floor 10", + "createnuclear.ponder.reactor_t3.text_12": "Floor 11", + "createnuclear.ponder.reactor_t3.text_13": "To start the reactor you will need liquid and rods corresponding to the pattern, then right click the controller with the blueprint in hand", + "createnuclear.ponder.reactor_t3.text_14": "Note: Check page 4 for I/O and Alarm blocks (placement & function).", + "createnuclear.ponder.reactor_t3.text_2": "Floor 2", + "createnuclear.ponder.reactor_t3.text_3": "Floor 3", + "createnuclear.ponder.reactor_t3.text_4": "Floor 4", + "createnuclear.ponder.reactor_t3.text_5": "Floor 5", + "createnuclear.ponder.reactor_t3.text_6": "Floor 6", + "createnuclear.ponder.reactor_t3.text_7": "Controller: brain of the reactor, and the place where the blueprint goes to start it", + "createnuclear.ponder.reactor_t3.text_8": "Floor 7", + "createnuclear.ponder.reactor_t3.text_9": "Floor 8", + "createnuclear.reactor.debug.label.alarm": "Alarm", + "createnuclear.reactor.debug.label.fluid_input": "Fluid Input", + "createnuclear.reactor.debug.label.input": "Input", + "createnuclear.reactor.debug.label.output": "Output", + "createnuclear.reactor.debug.registered_position": " registered @ %s", + "createnuclear.reactor.debug.summary": "%s: %s registered, %s valid", + "createnuclear.reactor.debug.title": "--- Reactor diagnostics ---", + "createnuclear.reactor.debug.valid_position": " valid @ %s", + "createnuclear.snow_powder.fan.recipe": "Cryogenic fan", + "createnuclear.subtitle.alarm/alarm": "Reactor Alarm Loop", + "createnuclear.subtitle.alarm/reactor_alarm": "Reactor Alarm", + "createnuclear.subtitle.biomes/wasteland": "Wasteland", + "createnuclear.subtitle.explosion/large_nuclear_explosion": "Large Nuclear Explosion", + "createnuclear.subtitle.explosion/main": "Nuclear Explosion Main", + "createnuclear.subtitle.explosion/nuclear_explosion": "Nuclear Explosion", + "createnuclear.subtitle.explosion/nuclear_explosion_rumble": "Nuclear Explosion Rumble", + "createnuclear.subtitle.explosion/ringing": "Nuclear Explosion Ringing", + "createnuclear.subtitle.explosion/rumble": "Nuclear Explosion Rumble", + "createnuclear.subtitle.explosion/shockwave": "Nuclear Explosion Shockwave", + "createnuclear.subtitle.geiger/high": "Geiger High", + "createnuclear.subtitle.geiger/low": "Geiger Low", + "createnuclear.subtitle.geiger/medium": "Geiger Medium", + "createnuclear.subtitle.reacteur/activation": "Reactor Activation", + "createnuclear.subtitle.reacteur/assemble_deassemble/motor_assemble": "Motor Assemble", + "createnuclear.subtitle.reacteur/assemble_deassemble/motor_disassemble": "Motor Disassemble", + "createnuclear.subtitle.reacteur/running": "Reactor Running", + "createnuclear.subtitle.reacteur/shut_off": "Reactor Shut Off", + "createnuclear.tooltip.baseRodHeat": "Base Rod Heat: %d Q", + "createnuclear.tooltip.cloth.color": "Color of armor piece: %s", + "createnuclear.tooltip.fluid": "Fluid: %s ", + "createnuclear.tooltip.fluid.amount": "%d mb", + "createnuclear.tooltip.fluid.none": "Fluid: None ", "createnuclear.tooltip.heatLevel": "Heat Level", "createnuclear.tooltip.heatLevel.caution": "Caution", "createnuclear.tooltip.heatLevel.danger": "Danger", "createnuclear.tooltip.heatLevel.none": "None", "createnuclear.tooltip.heatLevel.safety": "Safety", "createnuclear.tooltip.heatLevel.warning": "Warning", - "createnuclear.tooltip.item.graphene.rod": "Graphite Rod: ", + "createnuclear.tooltip.item.cooled.rod": "Cooler Rod: ", + "createnuclear.tooltip.item.empty.rod": "Input Items: ", + "createnuclear.tooltip.item.fuel.rod": "Fuel Rod: ", "createnuclear.tooltip.item.unknown.rod": "Unknown: ", - "createnuclear.tooltip.item.uranium.rod": "Uranium Rod: ", + "createnuclear.tooltip.proximityRodHeat": "Proximity Rod Heat: %.2f Q", + "createnuclear.tooltip.ratio": "Rod Value for ratio: %d", + "createnuclear.tooltip.rodTimer": "Rod Duration: %d tick", + "createnuclear.tooltip.statRod": "Rod Stat Pattern:", + "createnuclear.tooltip.typeRod": "Rod Type: %s", + "death.attack.createnuclear.fan_radiation": "%1$s died from radiation blast", + "death.attack.createnuclear.radiation": "%1$s died from radiation", + "effect.createnuclear.iodine": "Iodine", "effect.createnuclear.radiation": "Radiation", "emi.category.createnuclear.fan_enriched": "Bulk Enriching", + "emi.category.createnuclear.snow_powder": "Cryogenic fan", "entity.createnuclear.irradiated_cat": "Irradiated Cat", "entity.createnuclear.irradiated_chicken": "Irradiated Chicken", + "entity.createnuclear.irradiated_cow": "Irradiated Cow", "entity.createnuclear.irradiated_wolf": "Irradiated Wolf", + "entity.createnuclear.nuclear_explosion": "Nuclear Explosion", + "fluid.createnuclear.nitrogen": "Liquid Nitrogen", + "fluid.createnuclear.thorium": "Liquid Thorium", "fluid.createnuclear.uranium": "Liquid Uranium", "gui.createnuclear.reactor_controller.title": "Reactor Controller", "gui.createnuclear.reactor_input.title": "Reactor Input Storage", - "item.createnuclear.anti_radiation_boots": "Anti Radiation Boots", - "item.createnuclear.black_anti_radiation_chestplate": "Black Anti Radiation Chestplate", - "item.createnuclear.black_anti_radiation_helmet": "Black Anti Radiation Helmet", - "item.createnuclear.black_anti_radiation_leggings": "Black Anti Radiation Leggings", + "irradiated.taming.wip": "This creature cannot be tamed yet - irradiated mobs are still a work in progress", + "item.createnuclear.biome_irradiation_extractor": "Biome Irradiation Extractor", "item.createnuclear.black_cloth": "Black Cloth", - "item.createnuclear.blue_anti_radiation_chestplate": "Blue Anti Radiation Chestplate", - "item.createnuclear.blue_anti_radiation_helmet": "Blue Anti Radiation Helmet", - "item.createnuclear.blue_anti_radiation_leggings": "Blue Anti Radiation Leggings", "item.createnuclear.blue_cloth": "Blue Cloth", - "item.createnuclear.brown_anti_radiation_chestplate": "Brown Anti Radiation Chestplate", - "item.createnuclear.brown_anti_radiation_helmet": "Brown Anti Radiation Helmet", - "item.createnuclear.brown_anti_radiation_leggings": "Brown Anti Radiation Leggings", "item.createnuclear.brown_cloth": "Brown Cloth", "item.createnuclear.cat_irradiated_spawn_egg": "Irradiated Cat Spawn Egg", "item.createnuclear.chicken_irradiated_spawn_egg": "Irradiated Chicken Spawn Egg", "item.createnuclear.coal_dust": "Coal Dust", - "item.createnuclear.cyan_anti_radiation_chestplate": "Cyan Anti Radiation Chestplate", - "item.createnuclear.cyan_anti_radiation_helmet": "Cyan Anti Radiation Helmet", - "item.createnuclear.cyan_anti_radiation_leggings": "Cyan Anti Radiation Leggings", + "item.createnuclear.cooled_nitrogen_concentrate": "Cooled Nitrogen Concentrate", "item.createnuclear.cyan_cloth": "Cyan Cloth", + "item.createnuclear.default_anti_radiation_boots": "Anti Radiation Boots", + "item.createnuclear.default_anti_radiation_chestplate": "Anti Radiation Chestplate", + "item.createnuclear.default_anti_radiation_helmet": "Anti Radiation Helmet", + "item.createnuclear.default_anti_radiation_leggings": "Anti Radiation Leggings", "item.createnuclear.enriched_yellowcake": "Enriched Yellowcake", "item.createnuclear.graphene": "Graphene", "item.createnuclear.graphite_rod": "Graphite Rod", "item.createnuclear.graphite_rod.tooltip.summary": "_Stick_ to be used in the _reactor input_ to operate it.", - "item.createnuclear.gray_anti_radiation_chestplate": "Gray Anti Radiation Chestplate", - "item.createnuclear.gray_anti_radiation_helmet": "Gray Anti Radiation Helmet", - "item.createnuclear.gray_anti_radiation_leggings": "Gray Anti Radiation Leggings", "item.createnuclear.gray_cloth": "Gray Cloth", - "item.createnuclear.green_anti_radiation_chestplate": "Green Anti Radiation Chestplate", - "item.createnuclear.green_anti_radiation_helmet": "Green Anti Radiation Helmet", - "item.createnuclear.green_anti_radiation_leggings": "Green Anti Radiation Leggings", "item.createnuclear.green_cloth": "Green Cloth", "item.createnuclear.lead_ingot": "Lead Ingot", "item.createnuclear.lead_nugget": "Lead Nugget", - "item.createnuclear.light_blue_anti_radiation_chestplate": "Light Blue Anti Radiation Chestplate", - "item.createnuclear.light_blue_anti_radiation_helmet": "Light Blue Anti Radiation Helmet", - "item.createnuclear.light_blue_anti_radiation_leggings": "Light Blue Anti Radiation Leggings", "item.createnuclear.light_blue_cloth": "Light Blue Cloth", - "item.createnuclear.light_gray_anti_radiation_chestplate": "Light Gray Anti Radiation Chestplate", - "item.createnuclear.light_gray_anti_radiation_helmet": "Light Gray Anti Radiation Helmet", - "item.createnuclear.light_gray_anti_radiation_leggings": "Light Gray Anti Radiation Leggings", "item.createnuclear.light_gray_cloth": "Light Gray Cloth", - "item.createnuclear.lime_anti_radiation_chestplate": "Lime Anti Radiation Chestplate", - "item.createnuclear.lime_anti_radiation_helmet": "Lime Anti Radiation Helmet", - "item.createnuclear.lime_anti_radiation_leggings": "Lime Anti Radiation Leggings", "item.createnuclear.lime_cloth": "Lime Cloth", - "item.createnuclear.magenta_anti_radiation_chestplate": "Magenta Anti Radiation Chestplate", - "item.createnuclear.magenta_anti_radiation_helmet": "Magenta Anti Radiation Helmet", - "item.createnuclear.magenta_anti_radiation_leggings": "Magenta Anti Radiation Leggings", "item.createnuclear.magenta_cloth": "Magenta Cloth", - "item.createnuclear.orange_anti_radiation_chestplate": "Orange Anti Radiation Chestplate", - "item.createnuclear.orange_anti_radiation_helmet": "Orange Anti Radiation Helmet", - "item.createnuclear.orange_anti_radiation_leggings": "Orange Anti Radiation Leggings", + "item.createnuclear.nitrate": "Nitrate", + "item.createnuclear.nitrogen_bucket": "Nitrogen Bucket", + "item.createnuclear.nitrogen_concentrate": "Nitrogen Concentrate", "item.createnuclear.orange_cloth": "Orange Cloth", - "item.createnuclear.pink_anti_radiation_chestplate": "Pink Anti Radiation Chestplate", - "item.createnuclear.pink_anti_radiation_helmet": "Pink Anti Radiation Helmet", - "item.createnuclear.pink_anti_radiation_leggings": "Pink Anti Radiation Leggings", "item.createnuclear.pink_cloth": "Pink Cloth", - "item.createnuclear.purple_anti_radiation_chestplate": "Purple Anti Radiation Chestplate", - "item.createnuclear.purple_anti_radiation_helmet": "Purple Anti Radiation Helmet", - "item.createnuclear.purple_anti_radiation_leggings": "Purple Anti Radiation Leggings", "item.createnuclear.purple_cloth": "Purple Cloth", "item.createnuclear.raw_lead": "Raw Lead", + "item.createnuclear.raw_thorium": "Raw Thorium", "item.createnuclear.raw_uranium": "Raw Uranium", + "item.createnuclear.reactor_blueprint.chat_info": "Follow the link to open the documentation:", + "item.createnuclear.reactor_blueprint.tooltip": "Used to design and visualize the reactor's interior layout.", + "item.createnuclear.reactor_blueprint.tooltip_hint": "§7Press §eShift + Right Click §7to with the blueprint in hand to get the Wiki link.", + "item.createnuclear.reactor_blueprint.wiki_link": "[Open Official Wiki]", "item.createnuclear.reactor_blueprint_item": "Reactor Blueprint", "item.createnuclear.reactor_blueprint_item.tooltip.behaviour1": "_Right_ click to fill it.", "item.createnuclear.reactor_blueprint_item.tooltip.behaviour2": "_Right_ click on the reactor controller to open it.", - "item.createnuclear.reactor_blueprint_item.tooltip.condition1": "Filled with graphite and uranium rods", + "item.createnuclear.reactor_blueprint_item.tooltip.condition1": "Filled with cooling and fuel rods", "item.createnuclear.reactor_blueprint_item.tooltip.condition2": "The reactor must be assembled", "item.createnuclear.reactor_blueprint_item.tooltip.summary": "It allows you to configure your own pattern.", - "item.createnuclear.red_anti_radiation_chestplate": "Red Anti Radiation Chestplate", - "item.createnuclear.red_anti_radiation_helmet": "Red Anti Radiation Helmet", - "item.createnuclear.red_anti_radiation_leggings": "Red Anti Radiation Leggings", "item.createnuclear.red_cloth": "Red Cloth", + "item.createnuclear.reinforced_glass_bottle": "Reinforced Glass Bottle", "item.createnuclear.steel_ingot": "Steel Ingot", "item.createnuclear.steel_nugget": "Steel Nugget", + "item.createnuclear.thorium_bucket": "Thorium Bucket", + "item.createnuclear.thorium_dust": "Thorium Dust", + "item.createnuclear.thorium_ingot": "Thorium Ingot", + "item.createnuclear.thorium_nugget": "Thorium Nugget", + "item.createnuclear.thorium_rod": "Thorium Rod", "item.createnuclear.uranium_bucket": "Uranium Bucket", "item.createnuclear.uranium_powder": "Uranium Powder", "item.createnuclear.uranium_rod": "Uranium Rod", "item.createnuclear.uranium_rod.tooltip.summary": "_Stick_ to be used in the _reactor input_ to operate it.", - "item.createnuclear.white_anti_radiation_chestplate": "White Anti Radiation Chestplate", - "item.createnuclear.white_anti_radiation_helmet": "White Anti Radiation Helmet", - "item.createnuclear.white_anti_radiation_leggings": "White Anti Radiation Leggings", "item.createnuclear.white_cloth": "White Cloth", "item.createnuclear.wolf_irradiated_spawn_egg": "Irradiated Wolf Spawn Egg", - "item.createnuclear.yellow_anti_radiation_chestplate": "Yellow Anti Radiation Chestplate", - "item.createnuclear.yellow_anti_radiation_helmet": "Yellow Anti Radiation Helmet", - "item.createnuclear.yellow_anti_radiation_leggings": "Yellow Anti Radiation Leggings", "item.createnuclear.yellow_cloth": "Yellow Cloth", "item.createnuclear.yellowcake": "Yellowcake", + "item.minecraft.lingering_potion.effect.potion_of_iodine": "Lingering Potion of Iodine", + "item.minecraft.lingering_potion.effect.potion_of_iodine_augment": "Lingering Potion of Iodine", "item.minecraft.lingering_potion.effect.potion_of_radiation_1": "Lingering Potion of Radiation", "item.minecraft.lingering_potion.effect.potion_of_radiation_2": "Lingering Potion of Radiation", "item.minecraft.lingering_potion.effect.potion_of_radiation_augment_1": "Lingering Potion of Radiation", + "item.minecraft.potion.effect.potion_of_iodine": "Potion of Iodine", + "item.minecraft.potion.effect.potion_of_iodine_augment": "Potion of Iodine", "item.minecraft.potion.effect.potion_of_radiation_1": "Potion of Radiation", "item.minecraft.potion.effect.potion_of_radiation_2": "Potion of Radiation", "item.minecraft.potion.effect.potion_of_radiation_augment_1": "Potion of Radiation", + "item.minecraft.splash_potion.effect.potion_of_iodine": "Splash Potion of Iodine", + "item.minecraft.splash_potion.effect.potion_of_iodine_augment": "Splash Potion of Iodine", "item.minecraft.splash_potion.effect.potion_of_radiation_1": "Splash Potion of Radiation", "item.minecraft.splash_potion.effect.potion_of_radiation_2": "Splash Potion of Radiation", "item.minecraft.splash_potion.effect.potion_of_radiation_augment_1": "Splash Potion of Radiation", + "item.minecraft.tipped_arrow.effect.potion_of_iodine": "Arrow of Iodine", + "item.minecraft.tipped_arrow.effect.potion_of_iodine_augment": "Arrow of Iodine", "item.minecraft.tipped_arrow.effect.potion_of_radiation_1": "Arrow of Radiation", "item.minecraft.tipped_arrow.effect.potion_of_radiation_2": "Arrow of Radiation", "item.minecraft.tipped_arrow.effect.potion_of_radiation_augment_1": "Arrow of Radiation", diff --git a/src/generated/resources/assets/createnuclear/models/block/deepslate_nitrate_ore.json b/src/generated/resources/assets/createnuclear/models/block/deepslate_nitrate_ore.json new file mode 100644 index 0000000..7af5e2f --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/deepslate_nitrate_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "createnuclear:block/deepslate_nitrate_ore" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/deepslate_thorium_ore.json b/src/generated/resources/assets/createnuclear/models/block/deepslate_thorium_ore.json new file mode 100644 index 0000000..8ba7752 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/deepslate_thorium_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "createnuclear:block/deepslate_thorium_ore" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/nitrate_ore.json b/src/generated/resources/assets/createnuclear/models/block/nitrate_ore.json new file mode 100644 index 0000000..5754560 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/nitrate_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "createnuclear:block/nitrate_ore" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/nitrogen.json b/src/generated/resources/assets/createnuclear/models/block/nitrogen.json new file mode 100644 index 0000000..a48ca03 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/nitrogen.json @@ -0,0 +1,5 @@ +{ + "textures": { + "particle": "createnuclear:fluid/nitrogen_still" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/raw_thorium_block.json b/src/generated/resources/assets/createnuclear/models/block/raw_thorium_block.json new file mode 100644 index 0000000..9301bee --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/raw_thorium_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "createnuclear:block/raw_thorium_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/reactor/controller/off.json b/src/generated/resources/assets/createnuclear/models/block/reactor/controller/off.json new file mode 100644 index 0000000..fb38b94 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/reactor/controller/off.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:block/reactor/controller/block", + "textures": { + "1": "createnuclear:block/reactor/controller/controller_panel_off", + "particle": "createnuclear:block/reactor/controller/controller_panel_off" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/reactor/controller/on.json b/src/generated/resources/assets/createnuclear/models/block/reactor/controller/on.json new file mode 100644 index 0000000..423b3f4 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/reactor/controller/on.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:block/reactor/controller/block", + "textures": { + "1": "createnuclear:block/reactor/controller/controller_panel_on", + "particle": "createnuclear:block/reactor/controller/controller_panel_on" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/reactor/controller/standby.json b/src/generated/resources/assets/createnuclear/models/block/reactor/controller/standby.json new file mode 100644 index 0000000..59dc81d --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/reactor/controller/standby.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:block/reactor/controller/block", + "textures": { + "1": "createnuclear:block/reactor/controller/controller_panel_standby", + "particle": "createnuclear:block/reactor/controller/controller_panel_standby" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/reactor_alarm.json b/src/generated/resources/assets/createnuclear/models/block/reactor_alarm.json new file mode 100644 index 0000000..e78ea0f --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/reactor_alarm.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "createnuclear:block/reactor_alarm" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/reinforced_glass.json b/src/generated/resources/assets/createnuclear/models/block/reinforced_glass.json index 4c54b23..e5f6e98 100644 --- a/src/generated/resources/assets/createnuclear/models/block/reinforced_glass.json +++ b/src/generated/resources/assets/createnuclear/models/block/reinforced_glass.json @@ -1,5 +1,6 @@ { "parent": "minecraft:block/cube_all", + "render_type": "minecraft:translucent", "textures": { "all": "createnuclear:block/reactor/reinforced/glass", "particle": "createnuclear:block/reactor/reinforced/glass" diff --git a/src/generated/resources/assets/createnuclear/models/block/thorium.json b/src/generated/resources/assets/createnuclear/models/block/thorium.json new file mode 100644 index 0000000..5a6ef09 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/thorium.json @@ -0,0 +1,5 @@ +{ + "textures": { + "particle": "createnuclear:fluid/thorium_still" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/thorium_block.json b/src/generated/resources/assets/createnuclear/models/block/thorium_block.json new file mode 100644 index 0000000..1295cc9 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/thorium_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "createnuclear:block/thorium_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/block/thorium_ore.json b/src/generated/resources/assets/createnuclear/models/block/thorium_ore.json new file mode 100644 index 0000000..bc948d2 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/block/thorium_ore.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "createnuclear:block/thorium_ore" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/anti_radiation_boots.json deleted file mode 100644 index 703df56..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/anti_radiation_boots.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/anti_radiation_boots" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor.json b/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor.json new file mode 100644 index 0000000..5afa3b2 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "createnuclear:item/biome_irradiation_extractor/quarter", + "predicate": { + "createnuclear:biome_restore": 0.25 + } + }, + { + "model": "createnuclear:item/biome_irradiation_extractor/half", + "predicate": { + "createnuclear:biome_restore": 0.5 + } + }, + { + "model": "createnuclear:item/biome_irradiation_extractor/three_quarters", + "predicate": { + "createnuclear:biome_restore": 0.75 + } + }, + { + "model": "createnuclear:item/biome_irradiation_extractor/full", + "predicate": { + "createnuclear:biome_restore": 1.0 + } + } + ], + "textures": { + "layer0": "createnuclear:item/biome_irradiation_extractor/empty" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/full.json b/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/full.json new file mode 100644 index 0000000..1f07dae --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/full.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/biome_irradiation_extractor/full" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/half.json b/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/half.json new file mode 100644 index 0000000..25634c8 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/half.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/biome_irradiation_extractor/half" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/quarter.json b/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/quarter.json new file mode 100644 index 0000000..35b311a --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/quarter.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/biome_irradiation_extractor/quarter" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/three_quarters.json b/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/three_quarters.json new file mode 100644 index 0000000..dd251fd --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/biome_irradiation_extractor/three_quarters.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/biome_irradiation_extractor/three_quarters" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/black_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/black_anti_radiation_chestplate.json deleted file mode 100644 index 7d0d44a..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/black_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/black_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/black_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/black_anti_radiation_helmet.json deleted file mode 100644 index 46225ff..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/black_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/black_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/black_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/black_anti_radiation_leggings.json deleted file mode 100644 index a88edd4..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/black_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/black_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/blue_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/blue_anti_radiation_chestplate.json deleted file mode 100644 index 4ea98be..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/blue_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/blue_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/blue_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/blue_anti_radiation_helmet.json deleted file mode 100644 index e7c3759..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/blue_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/blue_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/blue_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/blue_anti_radiation_leggings.json deleted file mode 100644 index 5f9b8db..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/blue_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/blue_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/brown_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/brown_anti_radiation_chestplate.json deleted file mode 100644 index faa30b5..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/brown_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/brown_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/brown_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/brown_anti_radiation_helmet.json deleted file mode 100644 index cb65b39..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/brown_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/brown_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/brown_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/brown_anti_radiation_leggings.json deleted file mode 100644 index ebbf44e..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/brown_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/brown_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_boots.json new file mode 100644 index 0000000..c5d3b56 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/black_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_chestplate.json new file mode 100644 index 0000000..b372ed8 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/black_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_helmet.json new file mode 100644 index 0000000..5740ca1 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/black_anti_radiation_suit", + "particle": "createnuclear:models/armor/black_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_leggings.json new file mode 100644 index 0000000..3e0e501 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/black_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/black_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_boots.json new file mode 100644 index 0000000..cdd47b8 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/blue_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_chestplate.json new file mode 100644 index 0000000..0003ae5 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/blue_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_helmet.json new file mode 100644 index 0000000..ca4563b --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/blue_anti_radiation_suit", + "particle": "createnuclear:models/armor/blue_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_leggings.json new file mode 100644 index 0000000..fa14914 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/blue_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/blue_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_boots.json new file mode 100644 index 0000000..57c7d2f --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/brown_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_chestplate.json new file mode 100644 index 0000000..d513977 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/brown_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_helmet.json new file mode 100644 index 0000000..c9c6144 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/brown_anti_radiation_suit", + "particle": "createnuclear:models/armor/brown_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_leggings.json new file mode 100644 index 0000000..054a1b5 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/brown_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/brown_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_boots.json new file mode 100644 index 0000000..2094bf8 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/cyan_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_chestplate.json new file mode 100644 index 0000000..e547aa9 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/cyan_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_helmet.json new file mode 100644 index 0000000..6167aa1 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/cyan_anti_radiation_suit", + "particle": "createnuclear:models/armor/cyan_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_leggings.json new file mode 100644 index 0000000..58780ba --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/cyan_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/cyan_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_boots.json new file mode 100644 index 0000000..947ec4c --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/gray_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_chestplate.json new file mode 100644 index 0000000..62ac856 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/gray_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_helmet.json new file mode 100644 index 0000000..2582a91 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/gray_anti_radiation_suit", + "particle": "createnuclear:models/armor/gray_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_leggings.json new file mode 100644 index 0000000..99e8205 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/gray_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/gray_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_boots.json new file mode 100644 index 0000000..affda1a --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/green_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_chestplate.json new file mode 100644 index 0000000..67a13b1 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/green_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_helmet.json new file mode 100644 index 0000000..7272b42 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/green_anti_radiation_suit", + "particle": "createnuclear:models/armor/green_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_leggings.json new file mode 100644 index 0000000..dd87dc6 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/green_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/green_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_boots.json new file mode 100644 index 0000000..035ff00 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/light_blue_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_chestplate.json new file mode 100644 index 0000000..a0b9b48 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/light_blue_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_helmet.json new file mode 100644 index 0000000..0ac4ffe --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/light_blue_anti_radiation_suit", + "particle": "createnuclear:models/armor/light_blue_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_leggings.json new file mode 100644 index 0000000..2bca5d8 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/light_blue_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/light_blue_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_boots.json new file mode 100644 index 0000000..2be3da8 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/light_gray_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_chestplate.json new file mode 100644 index 0000000..128b545 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/light_gray_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_helmet.json new file mode 100644 index 0000000..d2d4952 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/light_gray_anti_radiation_suit", + "particle": "createnuclear:models/armor/light_gray_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_leggings.json new file mode 100644 index 0000000..2cd3118 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/light_gray_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/light_gray_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_boots.json new file mode 100644 index 0000000..c16598e --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/lime_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_chestplate.json new file mode 100644 index 0000000..af6a10d --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/lime_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_helmet.json new file mode 100644 index 0000000..47f1e9c --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/lime_anti_radiation_suit", + "particle": "createnuclear:models/armor/lime_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_leggings.json new file mode 100644 index 0000000..23573a9 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/lime_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/lime_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_boots.json new file mode 100644 index 0000000..a0ed037 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/magenta_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_chestplate.json new file mode 100644 index 0000000..92b957d --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/magenta_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_helmet.json new file mode 100644 index 0000000..d809cec --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/magenta_anti_radiation_suit", + "particle": "createnuclear:models/armor/magenta_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_leggings.json new file mode 100644 index 0000000..75641f2 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/magenta_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/magenta_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_boots.json new file mode 100644 index 0000000..b21c32c --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/orange_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_chestplate.json new file mode 100644 index 0000000..f4f2e64 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/orange_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_helmet.json new file mode 100644 index 0000000..453c9aa --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/orange_anti_radiation_suit", + "particle": "createnuclear:models/armor/orange_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_leggings.json new file mode 100644 index 0000000..d6768cb --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/orange_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/orange_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_boots.json new file mode 100644 index 0000000..dfb3686 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/pink_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_chestplate.json new file mode 100644 index 0000000..b0384f6 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/pink_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_helmet.json new file mode 100644 index 0000000..19eea2b --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/pink_anti_radiation_suit", + "particle": "createnuclear:models/armor/pink_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_leggings.json new file mode 100644 index 0000000..0e4ed9d --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/pink_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/pink_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_boots.json new file mode 100644 index 0000000..50ff9a2 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/purple_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_chestplate.json new file mode 100644 index 0000000..eaa6885 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/purple_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_helmet.json new file mode 100644 index 0000000..a4c79e8 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/purple_anti_radiation_suit", + "particle": "createnuclear:models/armor/purple_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_leggings.json new file mode 100644 index 0000000..ee1ddf3 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/purple_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/purple_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_boots.json new file mode 100644 index 0000000..07ac3d9 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/red_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_chestplate.json new file mode 100644 index 0000000..4e838fa --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/red_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_helmet.json new file mode 100644 index 0000000..66f9652 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/red_anti_radiation_suit", + "particle": "createnuclear:models/armor/red_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_leggings.json new file mode 100644 index 0000000..9b7436a --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/red_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/red_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_boots.json new file mode 100644 index 0000000..29c26ba --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/white_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_chestplate.json new file mode 100644 index 0000000..4f5f411 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/white_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_helmet.json new file mode 100644 index 0000000..152d28b --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/white_anti_radiation_suit", + "particle": "createnuclear:models/armor/white_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_leggings.json new file mode 100644 index 0000000..7e1a948 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/white_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/white_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_boots.json new file mode 100644 index 0000000..501e81f --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_boots/item", + "textures": { + "14": "createnuclear:models/armor/yellow_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_chestplate.json new file mode 100644 index 0000000..8a42ce7 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_chestplate/item", + "textures": { + "14": "createnuclear:models/armor/yellow_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_helmet.json new file mode 100644 index 0000000..d86a721 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_helmet.json @@ -0,0 +1,7 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_helmet/item", + "textures": { + "layer0": "createnuclear:models/armor/yellow_anti_radiation_suit", + "particle": "createnuclear:models/armor/yellow_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_leggings.json new file mode 100644 index 0000000..a713149 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/colored/yellow_anti_radiation_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "createnuclear:item/default_anti_radiation_leggings/item", + "textures": { + "14": "createnuclear:models/armor/yellow_anti_radiation_suit" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/cooled_nitrogen_concentrate.json b/src/generated/resources/assets/createnuclear/models/item/cooled_nitrogen_concentrate.json new file mode 100644 index 0000000..e122350 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/cooled_nitrogen_concentrate.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/cooled_nitrogen_concentrate" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/cyan_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/cyan_anti_radiation_chestplate.json deleted file mode 100644 index 04c605b..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/cyan_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/cyan_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/cyan_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/cyan_anti_radiation_helmet.json deleted file mode 100644 index 9c29042..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/cyan_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/cyan_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/cyan_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/cyan_anti_radiation_leggings.json deleted file mode 100644 index a7d6f25..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/cyan_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/cyan_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/deepslate_nitrate_ore.json b/src/generated/resources/assets/createnuclear/models/item/deepslate_nitrate_ore.json new file mode 100644 index 0000000..d0f8ebb --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/deepslate_nitrate_ore.json @@ -0,0 +1,3 @@ +{ + "parent": "createnuclear:block/deepslate_nitrate_ore" +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/deepslate_thorium_ore.json b/src/generated/resources/assets/createnuclear/models/item/deepslate_thorium_ore.json new file mode 100644 index 0000000..c7a358a --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/deepslate_thorium_ore.json @@ -0,0 +1,3 @@ +{ + "parent": "createnuclear:block/deepslate_thorium_ore" +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_boots.json b/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_boots.json new file mode 100644 index 0000000..7e2cc99 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_boots.json @@ -0,0 +1,104 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "createnuclear:item/colored/white_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.0625 + } + }, + { + "model": "createnuclear:item/colored/orange_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.125 + } + }, + { + "model": "createnuclear:item/colored/magenta_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.1875 + } + }, + { + "model": "createnuclear:item/colored/light_blue_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.25 + } + }, + { + "model": "createnuclear:item/colored/yellow_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.3125 + } + }, + { + "model": "createnuclear:item/colored/lime_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.375 + } + }, + { + "model": "createnuclear:item/colored/pink_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.4375 + } + }, + { + "model": "createnuclear:item/colored/gray_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.5 + } + }, + { + "model": "createnuclear:item/colored/light_gray_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.5625 + } + }, + { + "model": "createnuclear:item/colored/cyan_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.625 + } + }, + { + "model": "createnuclear:item/colored/purple_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.6875 + } + }, + { + "model": "createnuclear:item/colored/blue_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.75 + } + }, + { + "model": "createnuclear:item/colored/brown_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.8125 + } + }, + { + "model": "createnuclear:item/colored/green_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.875 + } + }, + { + "model": "createnuclear:item/colored/red_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 0.9375 + } + }, + { + "model": "createnuclear:item/colored/black_anti_radiation_boots", + "predicate": { + "createnuclear:cloth_color": 1.0 + } + } + ], + "textures": { + "layer0": "createnuclear:item/armors/default_anti_radiation_boots" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_chestplate.json new file mode 100644 index 0000000..b851ffa --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_chestplate.json @@ -0,0 +1,104 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "createnuclear:item/colored/white_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.0625 + } + }, + { + "model": "createnuclear:item/colored/orange_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.125 + } + }, + { + "model": "createnuclear:item/colored/magenta_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.1875 + } + }, + { + "model": "createnuclear:item/colored/light_blue_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.25 + } + }, + { + "model": "createnuclear:item/colored/yellow_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.3125 + } + }, + { + "model": "createnuclear:item/colored/lime_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.375 + } + }, + { + "model": "createnuclear:item/colored/pink_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.4375 + } + }, + { + "model": "createnuclear:item/colored/gray_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.5 + } + }, + { + "model": "createnuclear:item/colored/light_gray_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.5625 + } + }, + { + "model": "createnuclear:item/colored/cyan_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.625 + } + }, + { + "model": "createnuclear:item/colored/purple_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.6875 + } + }, + { + "model": "createnuclear:item/colored/blue_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.75 + } + }, + { + "model": "createnuclear:item/colored/brown_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.8125 + } + }, + { + "model": "createnuclear:item/colored/green_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.875 + } + }, + { + "model": "createnuclear:item/colored/red_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 0.9375 + } + }, + { + "model": "createnuclear:item/colored/black_anti_radiation_chestplate", + "predicate": { + "createnuclear:cloth_color": 1.0 + } + } + ], + "textures": { + "layer0": "createnuclear:item/armors/default_anti_radiation_chestplate" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_helmet.json new file mode 100644 index 0000000..53d4be4 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_helmet.json @@ -0,0 +1,104 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "createnuclear:item/colored/white_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.0625 + } + }, + { + "model": "createnuclear:item/colored/orange_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.125 + } + }, + { + "model": "createnuclear:item/colored/magenta_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.1875 + } + }, + { + "model": "createnuclear:item/colored/light_blue_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.25 + } + }, + { + "model": "createnuclear:item/colored/yellow_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.3125 + } + }, + { + "model": "createnuclear:item/colored/lime_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.375 + } + }, + { + "model": "createnuclear:item/colored/pink_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.4375 + } + }, + { + "model": "createnuclear:item/colored/gray_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.5 + } + }, + { + "model": "createnuclear:item/colored/light_gray_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.5625 + } + }, + { + "model": "createnuclear:item/colored/cyan_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.625 + } + }, + { + "model": "createnuclear:item/colored/purple_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.6875 + } + }, + { + "model": "createnuclear:item/colored/blue_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.75 + } + }, + { + "model": "createnuclear:item/colored/brown_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.8125 + } + }, + { + "model": "createnuclear:item/colored/green_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.875 + } + }, + { + "model": "createnuclear:item/colored/red_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 0.9375 + } + }, + { + "model": "createnuclear:item/colored/black_anti_radiation_helmet", + "predicate": { + "createnuclear:cloth_color": 1.0 + } + } + ], + "textures": { + "layer0": "createnuclear:item/armors/default_anti_radiation_helmet" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_leggings.json new file mode 100644 index 0000000..cc553f8 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/default_anti_radiation_leggings.json @@ -0,0 +1,104 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "createnuclear:item/colored/white_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.0625 + } + }, + { + "model": "createnuclear:item/colored/orange_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.125 + } + }, + { + "model": "createnuclear:item/colored/magenta_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.1875 + } + }, + { + "model": "createnuclear:item/colored/light_blue_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.25 + } + }, + { + "model": "createnuclear:item/colored/yellow_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.3125 + } + }, + { + "model": "createnuclear:item/colored/lime_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.375 + } + }, + { + "model": "createnuclear:item/colored/pink_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.4375 + } + }, + { + "model": "createnuclear:item/colored/gray_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.5 + } + }, + { + "model": "createnuclear:item/colored/light_gray_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.5625 + } + }, + { + "model": "createnuclear:item/colored/cyan_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.625 + } + }, + { + "model": "createnuclear:item/colored/purple_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.6875 + } + }, + { + "model": "createnuclear:item/colored/blue_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.75 + } + }, + { + "model": "createnuclear:item/colored/brown_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.8125 + } + }, + { + "model": "createnuclear:item/colored/green_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.875 + } + }, + { + "model": "createnuclear:item/colored/red_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 0.9375 + } + }, + { + "model": "createnuclear:item/colored/black_anti_radiation_leggings", + "predicate": { + "createnuclear:cloth_color": 1.0 + } + } + ], + "textures": { + "layer0": "createnuclear:item/armors/default_anti_radiation_leggings" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/gray_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/gray_anti_radiation_chestplate.json deleted file mode 100644 index 1572321..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/gray_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/gray_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/gray_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/gray_anti_radiation_helmet.json deleted file mode 100644 index ab33a1a..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/gray_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/gray_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/gray_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/gray_anti_radiation_leggings.json deleted file mode 100644 index 9708f7a..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/gray_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/gray_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/green_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/green_anti_radiation_chestplate.json deleted file mode 100644 index 624ba07..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/green_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/green_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/green_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/green_anti_radiation_helmet.json deleted file mode 100644 index c766bd2..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/green_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/green_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/green_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/green_anti_radiation_leggings.json deleted file mode 100644 index 07af99b..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/green_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/green_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/light_blue_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/light_blue_anti_radiation_chestplate.json deleted file mode 100644 index 03200d2..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/light_blue_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/light_blue_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/light_blue_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/light_blue_anti_radiation_helmet.json deleted file mode 100644 index 95498a8..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/light_blue_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/light_blue_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/light_blue_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/light_blue_anti_radiation_leggings.json deleted file mode 100644 index 79eb600..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/light_blue_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/light_blue_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/light_gray_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/light_gray_anti_radiation_chestplate.json deleted file mode 100644 index e30f93f..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/light_gray_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/light_gray_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/light_gray_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/light_gray_anti_radiation_helmet.json deleted file mode 100644 index 9aeb29d..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/light_gray_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/light_gray_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/light_gray_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/light_gray_anti_radiation_leggings.json deleted file mode 100644 index a1e91cf..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/light_gray_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/light_gray_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/lime_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/lime_anti_radiation_chestplate.json deleted file mode 100644 index f4f7f96..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/lime_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/lime_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/lime_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/lime_anti_radiation_helmet.json deleted file mode 100644 index 1e7eb90..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/lime_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/lime_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/lime_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/lime_anti_radiation_leggings.json deleted file mode 100644 index 87466b5..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/lime_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/lime_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/magenta_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/magenta_anti_radiation_chestplate.json deleted file mode 100644 index 6247298..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/magenta_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/magenta_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/magenta_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/magenta_anti_radiation_helmet.json deleted file mode 100644 index 16f6f18..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/magenta_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/magenta_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/magenta_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/magenta_anti_radiation_leggings.json deleted file mode 100644 index a7da5fd..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/magenta_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/magenta_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/nitrate.json b/src/generated/resources/assets/createnuclear/models/item/nitrate.json new file mode 100644 index 0000000..b5e84b4 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/nitrate.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/nitrate" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/nitrate_ore.json b/src/generated/resources/assets/createnuclear/models/item/nitrate_ore.json new file mode 100644 index 0000000..47e5d87 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/nitrate_ore.json @@ -0,0 +1,3 @@ +{ + "parent": "createnuclear:block/nitrate_ore" +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/nitrogen_bucket.json b/src/generated/resources/assets/createnuclear/models/item/nitrogen_bucket.json new file mode 100644 index 0000000..8b1e966 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/nitrogen_bucket.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/nitrogen_bucket" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/nitrogen_concentrate.json b/src/generated/resources/assets/createnuclear/models/item/nitrogen_concentrate.json new file mode 100644 index 0000000..80476cb --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/nitrogen_concentrate.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/nitrogen_concentrate" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/orange_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/orange_anti_radiation_chestplate.json deleted file mode 100644 index ce18ac3..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/orange_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/orange_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/orange_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/orange_anti_radiation_helmet.json deleted file mode 100644 index c922ae5..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/orange_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/orange_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/orange_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/orange_anti_radiation_leggings.json deleted file mode 100644 index 202a468..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/orange_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/orange_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/pink_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/pink_anti_radiation_chestplate.json deleted file mode 100644 index a24f101..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/pink_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/pink_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/pink_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/pink_anti_radiation_helmet.json deleted file mode 100644 index 6ec17b1..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/pink_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/pink_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/pink_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/pink_anti_radiation_leggings.json deleted file mode 100644 index 58b1c4a..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/pink_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/pink_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/purple_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/purple_anti_radiation_chestplate.json deleted file mode 100644 index 3e9009b..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/purple_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/purple_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/purple_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/purple_anti_radiation_helmet.json deleted file mode 100644 index 748b018..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/purple_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/purple_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/purple_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/purple_anti_radiation_leggings.json deleted file mode 100644 index 001024b..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/purple_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/purple_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/raw_thorium.json b/src/generated/resources/assets/createnuclear/models/item/raw_thorium.json new file mode 100644 index 0000000..82bb96b --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/raw_thorium.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/raw_thorium" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/raw_thorium_block.json b/src/generated/resources/assets/createnuclear/models/item/raw_thorium_block.json new file mode 100644 index 0000000..b75c195 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/raw_thorium_block.json @@ -0,0 +1,3 @@ +{ + "parent": "createnuclear:block/raw_thorium_block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/reactor_alarm.json b/src/generated/resources/assets/createnuclear/models/item/reactor_alarm.json new file mode 100644 index 0000000..889a06e --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/reactor_alarm.json @@ -0,0 +1,3 @@ +{ + "parent": "createnuclear:block/reactor_alarm" +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/reactor_fluid_input.json b/src/generated/resources/assets/createnuclear/models/item/reactor_fluid_input.json new file mode 100644 index 0000000..9def8ea --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/reactor_fluid_input.json @@ -0,0 +1,3 @@ +{ + "parent": "createnuclear:block/reactor/fluid_input/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/reactor_input.json b/src/generated/resources/assets/createnuclear/models/item/reactor_input.json deleted file mode 100644 index b4175b2..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/reactor_input.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "parent": "createnuclear:block/reactor/input/item" -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/reactor_rod_input.json b/src/generated/resources/assets/createnuclear/models/item/reactor_rod_input.json new file mode 100644 index 0000000..5fe1a68 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/reactor_rod_input.json @@ -0,0 +1,3 @@ +{ + "parent": "createnuclear:block/reactor/rod_input/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/red_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/red_anti_radiation_chestplate.json deleted file mode 100644 index 7e71188..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/red_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/red_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/red_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/red_anti_radiation_helmet.json deleted file mode 100644 index a4736bd..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/red_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/red_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/red_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/red_anti_radiation_leggings.json deleted file mode 100644 index 5240898..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/red_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/red_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/reinforced_glass_bottle.json b/src/generated/resources/assets/createnuclear/models/item/reinforced_glass_bottle.json new file mode 100644 index 0000000..c29947f --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/reinforced_glass_bottle.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/reinforced_glass_bottle" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/thorium_block.json b/src/generated/resources/assets/createnuclear/models/item/thorium_block.json new file mode 100644 index 0000000..94d3fcb --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/thorium_block.json @@ -0,0 +1,3 @@ +{ + "parent": "createnuclear:block/thorium_block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/thorium_bucket.json b/src/generated/resources/assets/createnuclear/models/item/thorium_bucket.json new file mode 100644 index 0000000..2a48a34 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/thorium_bucket.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/thorium_bucket" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/thorium_dust.json b/src/generated/resources/assets/createnuclear/models/item/thorium_dust.json new file mode 100644 index 0000000..7c6ab4d --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/thorium_dust.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/thorium_dust" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/thorium_ingot.json b/src/generated/resources/assets/createnuclear/models/item/thorium_ingot.json new file mode 100644 index 0000000..3cfe5d7 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/thorium_ingot.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/thorium_ingot" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/thorium_nugget.json b/src/generated/resources/assets/createnuclear/models/item/thorium_nugget.json new file mode 100644 index 0000000..3389988 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/thorium_nugget.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/thorium_nugget" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/thorium_ore.json b/src/generated/resources/assets/createnuclear/models/item/thorium_ore.json new file mode 100644 index 0000000..c0ce70c --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/thorium_ore.json @@ -0,0 +1,3 @@ +{ + "parent": "createnuclear:block/thorium_ore" +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/thorium_rod.json b/src/generated/resources/assets/createnuclear/models/item/thorium_rod.json new file mode 100644 index 0000000..9f31f8a --- /dev/null +++ b/src/generated/resources/assets/createnuclear/models/item/thorium_rod.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "createnuclear:item/thorium_rod" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/white_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/white_anti_radiation_chestplate.json deleted file mode 100644 index a5d91e2..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/white_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/white_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/white_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/white_anti_radiation_helmet.json deleted file mode 100644 index c203cda..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/white_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/white_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/white_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/white_anti_radiation_leggings.json deleted file mode 100644 index f6d419c..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/white_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/white_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/yellow_anti_radiation_chestplate.json b/src/generated/resources/assets/createnuclear/models/item/yellow_anti_radiation_chestplate.json deleted file mode 100644 index e66b6d4..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/yellow_anti_radiation_chestplate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/chestplates/yellow_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/yellow_anti_radiation_helmet.json b/src/generated/resources/assets/createnuclear/models/item/yellow_anti_radiation_helmet.json deleted file mode 100644 index 6b76a43..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/yellow_anti_radiation_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/helmets/yellow_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/models/item/yellow_anti_radiation_leggings.json b/src/generated/resources/assets/createnuclear/models/item/yellow_anti_radiation_leggings.json deleted file mode 100644 index 6180326..0000000 --- a/src/generated/resources/assets/createnuclear/models/item/yellow_anti_radiation_leggings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "createnuclear:item/armors/leggings/yellow_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/createnuclear/sounds.json b/src/generated/resources/assets/createnuclear/sounds.json new file mode 100644 index 0000000..94a5774 --- /dev/null +++ b/src/generated/resources/assets/createnuclear/sounds.json @@ -0,0 +1,164 @@ +{ + "alarm/alarm": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:alarm/alarm" + } + ], + "subtitle": "createnuclear.subtitle.alarm/alarm" + }, + "alarm/reactor_alarm": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:alarm/reactor_alarm" + } + ], + "subtitle": "createnuclear.subtitle.alarm/reactor_alarm" + }, + "biomes/wasteland": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:biomes/wasteland" + } + ], + "subtitle": "createnuclear.subtitle.biomes/wasteland" + }, + "explosion/large_nuclear_explosion": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:explosion/large_nuclear_explosion" + } + ], + "subtitle": "createnuclear.subtitle.explosion/large_nuclear_explosion" + }, + "explosion/main": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:explosion/main" + } + ], + "subtitle": "createnuclear.subtitle.explosion/main" + }, + "explosion/nuclear_explosion": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:explosion/nuclear_explosion" + } + ], + "subtitle": "createnuclear.subtitle.explosion/nuclear_explosion" + }, + "explosion/nuclear_explosion_rumble": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:explosion/nuclear_explosion_rumble" + } + ], + "subtitle": "createnuclear.subtitle.explosion/nuclear_explosion_rumble" + }, + "explosion/ringing": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:explosion/ringing" + } + ], + "subtitle": "createnuclear.subtitle.explosion/ringing" + }, + "explosion/rumble": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:explosion/rumble" + } + ], + "subtitle": "createnuclear.subtitle.explosion/rumble" + }, + "explosion/shockwave": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:explosion/shockwave" + } + ], + "subtitle": "createnuclear.subtitle.explosion/shockwave" + }, + "geiger/high": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:geiger/high" + } + ], + "subtitle": "createnuclear.subtitle.geiger/high" + }, + "geiger/low": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:geiger/low" + } + ], + "subtitle": "createnuclear.subtitle.geiger/low" + }, + "geiger/medium": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:geiger/medium" + } + ], + "subtitle": "createnuclear.subtitle.geiger/medium" + }, + "reacteur/activation": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:reacteur/activation" + } + ], + "subtitle": "createnuclear.subtitle.reacteur/activation" + }, + "reacteur/assemble_deassemble/motor_assemble": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:reacteur/assemble_deassemble/motor_assemble" + } + ], + "subtitle": "createnuclear.subtitle.reacteur/assemble_deassemble/motor_assemble" + }, + "reacteur/assemble_deassemble/motor_disassemble": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:reacteur/assemble_deassemble/motor_disassemble" + } + ], + "subtitle": "createnuclear.subtitle.reacteur/assemble_deassemble/motor_disassemble" + }, + "reacteur/running": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:reacteur/running" + } + ], + "subtitle": "createnuclear.subtitle.reacteur/running" + }, + "reacteur/shut_off": { + "sounds": [ + { + "type": "file", + "name": "createnuclear:reacteur/shut_off" + } + ], + "subtitle": "createnuclear.subtitle.reacteur/shut_off" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/ores.json b/src/generated/resources/data/c/tags/block/ores.json index 52471c4..c393b20 100644 --- a/src/generated/resources/data/c/tags/block/ores.json +++ b/src/generated/resources/data/c/tags/block/ores.json @@ -1,8 +1,12 @@ { "values": [ + "createnuclear:deepslate_uranium_ore", "createnuclear:deepslate_lead_ore", + "createnuclear:deepslate_thorium_ore", + "createnuclear:uranium_ore", "createnuclear:lead_ore", - "createnuclear:deepslate_uranium_ore", - "createnuclear:uranium_ore" + "createnuclear:thorium_ore", + "createnuclear:nitrate_ore", + "createnuclear:deepslate_nitrate_ore" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/ores/nitrate.json b/src/generated/resources/data/c/tags/block/ores/nitrate.json new file mode 100644 index 0000000..e306fa6 --- /dev/null +++ b/src/generated/resources/data/c/tags/block/ores/nitrate.json @@ -0,0 +1,6 @@ +{ + "values": [ + "createnuclear:nitrate_ore", + "createnuclear:deepslate_nitrate_ore" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/ores/thorium.json b/src/generated/resources/data/c/tags/block/ores/thorium.json new file mode 100644 index 0000000..c5f8a42 --- /dev/null +++ b/src/generated/resources/data/c/tags/block/ores/thorium.json @@ -0,0 +1,6 @@ +{ + "values": [ + "createnuclear:deepslate_thorium_ore", + "createnuclear:thorium_ore" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/ores_in_ground/deepslate.json b/src/generated/resources/data/c/tags/block/ores_in_ground/deepslate.json index f66bbd4..5d99e44 100644 --- a/src/generated/resources/data/c/tags/block/ores_in_ground/deepslate.json +++ b/src/generated/resources/data/c/tags/block/ores_in_ground/deepslate.json @@ -1,6 +1,8 @@ { "values": [ + "createnuclear:deepslate_uranium_ore", "createnuclear:deepslate_lead_ore", - "createnuclear:deepslate_uranium_ore" + "createnuclear:deepslate_thorium_ore", + "createnuclear:deepslate_nitrate_ore" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/ores_in_ground/stone.json b/src/generated/resources/data/c/tags/block/ores_in_ground/stone.json index a8a95f5..c257624 100644 --- a/src/generated/resources/data/c/tags/block/ores_in_ground/stone.json +++ b/src/generated/resources/data/c/tags/block/ores_in_ground/stone.json @@ -1,6 +1,8 @@ { "values": [ + "createnuclear:uranium_ore", "createnuclear:lead_ore", - "createnuclear:uranium_ore" + "createnuclear:thorium_ore", + "createnuclear:nitrate_ore" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/storage_blocks.json b/src/generated/resources/data/c/tags/block/storage_blocks.json new file mode 100644 index 0000000..f6dad32 --- /dev/null +++ b/src/generated/resources/data/c/tags/block/storage_blocks.json @@ -0,0 +1,10 @@ +{ + "values": [ + "createnuclear:raw_uranium_block", + "createnuclear:raw_lead_block", + "createnuclear:raw_thorium_block", + "createnuclear:lead_block", + "createnuclear:thorium_block", + "createnuclear:steel_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/storage_blocks/raw_thorium.json b/src/generated/resources/data/c/tags/block/storage_blocks/raw_thorium.json new file mode 100644 index 0000000..3bb2b80 --- /dev/null +++ b/src/generated/resources/data/c/tags/block/storage_blocks/raw_thorium.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:raw_thorium_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/block/storage_blocks/thorium.json b/src/generated/resources/data/c/tags/block/storage_blocks/thorium.json new file mode 100644 index 0000000..6ea006d --- /dev/null +++ b/src/generated/resources/data/c/tags/block/storage_blocks/thorium.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:thorium_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/armors.json b/src/generated/resources/data/c/tags/item/armors.json new file mode 100644 index 0000000..0fdc0c1 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/armors.json @@ -0,0 +1,8 @@ +{ + "values": [ + "createnuclear:default_anti_radiation_helmet", + "createnuclear:default_anti_radiation_chestplate", + "createnuclear:default_anti_radiation_leggings", + "createnuclear:default_anti_radiation_boots" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/armors/boots.json b/src/generated/resources/data/c/tags/item/armors/boots.json index 3e6a775..c945fe9 100644 --- a/src/generated/resources/data/c/tags/item/armors/boots.json +++ b/src/generated/resources/data/c/tags/item/armors/boots.json @@ -1,5 +1,5 @@ { "values": [ - "createnuclear:anti_radiation_boots" + "createnuclear:default_anti_radiation_boots" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/armors/chestplates.json b/src/generated/resources/data/c/tags/item/armors/chestplates.json index 8b659b8..6ee7aa9 100644 --- a/src/generated/resources/data/c/tags/item/armors/chestplates.json +++ b/src/generated/resources/data/c/tags/item/armors/chestplates.json @@ -1,20 +1,5 @@ { "values": [ - "createnuclear:white_anti_radiation_chestplate", - "createnuclear:orange_anti_radiation_chestplate", - "createnuclear:magenta_anti_radiation_chestplate", - "createnuclear:light_blue_anti_radiation_chestplate", - "createnuclear:yellow_anti_radiation_chestplate", - "createnuclear:lime_anti_radiation_chestplate", - "createnuclear:pink_anti_radiation_chestplate", - "createnuclear:gray_anti_radiation_chestplate", - "createnuclear:light_gray_anti_radiation_chestplate", - "createnuclear:cyan_anti_radiation_chestplate", - "createnuclear:purple_anti_radiation_chestplate", - "createnuclear:blue_anti_radiation_chestplate", - "createnuclear:brown_anti_radiation_chestplate", - "createnuclear:green_anti_radiation_chestplate", - "createnuclear:red_anti_radiation_chestplate", - "createnuclear:black_anti_radiation_chestplate" + "createnuclear:default_anti_radiation_chestplate" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/armors/helmets.json b/src/generated/resources/data/c/tags/item/armors/helmets.json index 7d378f7..855fd1a 100644 --- a/src/generated/resources/data/c/tags/item/armors/helmets.json +++ b/src/generated/resources/data/c/tags/item/armors/helmets.json @@ -1,20 +1,5 @@ { "values": [ - "createnuclear:white_anti_radiation_helmet", - "createnuclear:orange_anti_radiation_helmet", - "createnuclear:magenta_anti_radiation_helmet", - "createnuclear:light_blue_anti_radiation_helmet", - "createnuclear:yellow_anti_radiation_helmet", - "createnuclear:lime_anti_radiation_helmet", - "createnuclear:pink_anti_radiation_helmet", - "createnuclear:gray_anti_radiation_helmet", - "createnuclear:light_gray_anti_radiation_helmet", - "createnuclear:cyan_anti_radiation_helmet", - "createnuclear:purple_anti_radiation_helmet", - "createnuclear:blue_anti_radiation_helmet", - "createnuclear:brown_anti_radiation_helmet", - "createnuclear:green_anti_radiation_helmet", - "createnuclear:red_anti_radiation_helmet", - "createnuclear:black_anti_radiation_helmet" + "createnuclear:default_anti_radiation_helmet" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/armors/leggings.json b/src/generated/resources/data/c/tags/item/armors/leggings.json index ea23843..cbd5fb4 100644 --- a/src/generated/resources/data/c/tags/item/armors/leggings.json +++ b/src/generated/resources/data/c/tags/item/armors/leggings.json @@ -1,20 +1,5 @@ { "values": [ - "createnuclear:white_anti_radiation_leggings", - "createnuclear:orange_anti_radiation_leggings", - "createnuclear:magenta_anti_radiation_leggings", - "createnuclear:light_blue_anti_radiation_leggings", - "createnuclear:yellow_anti_radiation_leggings", - "createnuclear:lime_anti_radiation_leggings", - "createnuclear:pink_anti_radiation_leggings", - "createnuclear:gray_anti_radiation_leggings", - "createnuclear:light_gray_anti_radiation_leggings", - "createnuclear:cyan_anti_radiation_leggings", - "createnuclear:purple_anti_radiation_leggings", - "createnuclear:blue_anti_radiation_leggings", - "createnuclear:brown_anti_radiation_leggings", - "createnuclear:green_anti_radiation_leggings", - "createnuclear:red_anti_radiation_leggings", - "createnuclear:black_anti_radiation_leggings" + "createnuclear:default_anti_radiation_leggings" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/buckets/nitrogen.json b/src/generated/resources/data/c/tags/item/buckets/nitrogen.json new file mode 100644 index 0000000..062ab2c --- /dev/null +++ b/src/generated/resources/data/c/tags/item/buckets/nitrogen.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:nitrogen_bucket" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/buckets/thorium.json b/src/generated/resources/data/c/tags/item/buckets/thorium.json new file mode 100644 index 0000000..6aec424 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/buckets/thorium.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:thorium_bucket" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/buckets/uranium.json b/src/generated/resources/data/c/tags/item/buckets/uranium.json new file mode 100644 index 0000000..68a93e1 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/buckets/uranium.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:uranium_bucket" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/dusts.json b/src/generated/resources/data/c/tags/item/dusts.json index 16ed229..f00f2b4 100644 --- a/src/generated/resources/data/c/tags/item/dusts.json +++ b/src/generated/resources/data/c/tags/item/dusts.json @@ -1,6 +1,7 @@ { "values": [ "createnuclear:uranium_powder", - "createnuclear:coal_dust" + "createnuclear:coal_dust", + "createnuclear:thorium_dust" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/dusts/thorium.json b/src/generated/resources/data/c/tags/item/dusts/thorium.json new file mode 100644 index 0000000..9b0a353 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/dusts/thorium.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:thorium_dust" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ingots.json b/src/generated/resources/data/c/tags/item/ingots.json index 70e4923..069fcb8 100644 --- a/src/generated/resources/data/c/tags/item/ingots.json +++ b/src/generated/resources/data/c/tags/item/ingots.json @@ -1,6 +1,7 @@ { "values": [ "createnuclear:steel_ingot", - "createnuclear:lead_ingot" + "createnuclear:lead_ingot", + "createnuclear:thorium_ingot" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ingots/thorium.json b/src/generated/resources/data/c/tags/item/ingots/thorium.json new file mode 100644 index 0000000..ebbb559 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ingots/thorium.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:thorium_ingot" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/nuggets.json b/src/generated/resources/data/c/tags/item/nuggets.json index 8cf12e2..4683ae5 100644 --- a/src/generated/resources/data/c/tags/item/nuggets.json +++ b/src/generated/resources/data/c/tags/item/nuggets.json @@ -1,6 +1,7 @@ { "values": [ "createnuclear:steel_nugget", - "createnuclear:lead_nugget" + "createnuclear:lead_nugget", + "createnuclear:thorium_nugget" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/nuggets/thorium.json b/src/generated/resources/data/c/tags/item/nuggets/thorium.json new file mode 100644 index 0000000..6e41e83 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/nuggets/thorium.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:thorium_nugget" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ores.json b/src/generated/resources/data/c/tags/item/ores.json new file mode 100644 index 0000000..c393b20 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ores.json @@ -0,0 +1,12 @@ +{ + "values": [ + "createnuclear:deepslate_uranium_ore", + "createnuclear:deepslate_lead_ore", + "createnuclear:deepslate_thorium_ore", + "createnuclear:uranium_ore", + "createnuclear:lead_ore", + "createnuclear:thorium_ore", + "createnuclear:nitrate_ore", + "createnuclear:deepslate_nitrate_ore" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ores/nitrate.json b/src/generated/resources/data/c/tags/item/ores/nitrate.json new file mode 100644 index 0000000..e306fa6 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ores/nitrate.json @@ -0,0 +1,6 @@ +{ + "values": [ + "createnuclear:nitrate_ore", + "createnuclear:deepslate_nitrate_ore" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ores/thorium.json b/src/generated/resources/data/c/tags/item/ores/thorium.json new file mode 100644 index 0000000..c5f8a42 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ores/thorium.json @@ -0,0 +1,6 @@ +{ + "values": [ + "createnuclear:deepslate_thorium_ore", + "createnuclear:thorium_ore" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/raw_materials.json b/src/generated/resources/data/c/tags/item/raw_materials.json index 801e2f1..7024a1a 100644 --- a/src/generated/resources/data/c/tags/item/raw_materials.json +++ b/src/generated/resources/data/c/tags/item/raw_materials.json @@ -1,6 +1,7 @@ { "values": [ + "createnuclear:raw_uranium", "createnuclear:raw_lead", - "createnuclear:raw_uranium" + "createnuclear:raw_thorium" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/raw_materials/thorium.json b/src/generated/resources/data/c/tags/item/raw_materials/thorium.json new file mode 100644 index 0000000..e2f43fb --- /dev/null +++ b/src/generated/resources/data/c/tags/item/raw_materials/thorium.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:raw_thorium" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/raw_ores.json b/src/generated/resources/data/c/tags/item/raw_ores.json index 801e2f1..7024a1a 100644 --- a/src/generated/resources/data/c/tags/item/raw_ores.json +++ b/src/generated/resources/data/c/tags/item/raw_ores.json @@ -1,6 +1,7 @@ { "values": [ + "createnuclear:raw_uranium", "createnuclear:raw_lead", - "createnuclear:raw_uranium" + "createnuclear:raw_thorium" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/rods.json b/src/generated/resources/data/c/tags/item/rods.json index b665274..46b519a 100644 --- a/src/generated/resources/data/c/tags/item/rods.json +++ b/src/generated/resources/data/c/tags/item/rods.json @@ -1,6 +1,7 @@ { "values": [ + "createnuclear:uranium_rod", "createnuclear:graphite_rod", - "createnuclear:uranium_rod" + "createnuclear:thorium_rod" ] } \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/storage_blocks.json b/src/generated/resources/data/c/tags/item/storage_blocks.json new file mode 100644 index 0000000..f6dad32 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/storage_blocks.json @@ -0,0 +1,10 @@ +{ + "values": [ + "createnuclear:raw_uranium_block", + "createnuclear:raw_lead_block", + "createnuclear:raw_thorium_block", + "createnuclear:lead_block", + "createnuclear:thorium_block", + "createnuclear:steel_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/storage_blocks/raw_thorium.json b/src/generated/resources/data/c/tags/item/storage_blocks/raw_thorium.json new file mode 100644 index 0000000..3bb2b80 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/storage_blocks/raw_thorium.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:raw_thorium_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/storage_blocks/thorium.json b/src/generated/resources/data/c/tags/item/storage_blocks/thorium.json new file mode 100644 index 0000000..6ea006d --- /dev/null +++ b/src/generated/resources/data/c/tags/item/storage_blocks/thorium.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:thorium_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/absolute_zero.json b/src/generated/resources/data/createnuclear/advancement/absolute_zero.json new file mode 100644 index 0000000..b3b11e4 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/absolute_zero.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:chill_out", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:nitrogen_bucket" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.absolute_zero.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:nitrogen_bucket" + }, + "title": { + "translate": "advancement.createnuclear.absolute_zero" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/anti_radiation_armor.json b/src/generated/resources/data/createnuclear/advancement/anti_radiation_armor.json index 937b912..d938757 100644 --- a/src/generated/resources/data/createnuclear/advancement/anti_radiation_armor.json +++ b/src/generated/resources/data/createnuclear/advancement/anti_radiation_armor.json @@ -5,7 +5,7 @@ "conditions": { "items": [ { - "items": "#createnuclear:all_anti_radiation_armors" + "items": "#createnuclear:anti_radiation_armor" } ] }, @@ -20,7 +20,7 @@ }, "icon": { "count": 1, - "id": "createnuclear:white_anti_radiation_helmet" + "id": "createnuclear:default_anti_radiation_helmet" }, "title": { "translate": "advancement.createnuclear.anti_radiation_armor" diff --git a/src/generated/resources/data/createnuclear/advancement/automatic_uranium.json b/src/generated/resources/data/createnuclear/advancement/automatic_uranium.json index 2502e19..9682ffc 100644 --- a/src/generated/resources/data/createnuclear/advancement/automatic_uranium.json +++ b/src/generated/resources/data/createnuclear/advancement/automatic_uranium.json @@ -2,7 +2,7 @@ "parent": "createnuclear:root", "criteria": { "0": { - "trigger": "create:automatic_uranium_builtin" + "trigger": "createnuclear:automatic_uranium_builtin" } }, "display": { diff --git a/src/generated/resources/data/createnuclear/advancement/avoiding_cancer.json b/src/generated/resources/data/createnuclear/advancement/avoiding_cancer.json new file mode 100644 index 0000000..a28b70c --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/avoiding_cancer.json @@ -0,0 +1,53 @@ +{ + "parent": "createnuclear:anti_radiation_armor", + "criteria": { + "0": { + "conditions": { + "player": [ + { + "condition": "minecraft:entity_properties", + "entity": "this", + "predicate": { + "type": "minecraft:player", + "equipment": { + "chest": { + "items": "createnuclear:default_anti_radiation_chestplate" + }, + "feet": { + "items": "createnuclear:default_anti_radiation_boots" + }, + "head": { + "items": "createnuclear:default_anti_radiation_helmet" + }, + "legs": { + "items": "createnuclear:default_anti_radiation_leggings" + } + } + } + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.avoiding_cancer.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "title": { + "translate": "advancement.createnuclear.avoiding_cancer" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/chemistry_101.json b/src/generated/resources/data/createnuclear/advancement/chemistry_101.json new file mode 100644 index 0000000..c203f61 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/chemistry_101.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:root", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:nitrate" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.chemistry_101.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:nitrate" + }, + "title": { + "translate": "advancement.createnuclear.chemistry_101" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/chill_out.json b/src/generated/resources/data/createnuclear/advancement/chill_out.json new file mode 100644 index 0000000..2902c10 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/chill_out.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:getting_concentrated", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:cooled_nitrogen_concentrate" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.chill_out.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:cooled_nitrogen_concentrate" + }, + "title": { + "translate": "advancement.createnuclear.chill_out" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/craft_enriching_campfire.json b/src/generated/resources/data/createnuclear/advancement/craft_enriching_campfire.json new file mode 100644 index 0000000..c8f0841 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/craft_enriching_campfire.json @@ -0,0 +1,42 @@ +{ + "parent": "createnuclear:root", + "criteria": { + "0": { + "conditions": { + "ingredients": [ + { + "items": "createnuclear:enriched_soul_soil" + }, + { + "items": "#minecraft:logs" + }, + { + "items": "#c:rods/wooden" + } + ], + "recipe_id": "createnuclear:crafting/enriching_campfire" + }, + "trigger": "minecraft:recipe_crafted" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.craft_enriching_campfire.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:enriching_campfire" + }, + "title": { + "translate": "advancement.createnuclear.craft_enriching_campfire" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/crunchy_uranium.json b/src/generated/resources/data/createnuclear/advancement/crunchy_uranium.json new file mode 100644 index 0000000..55c49a1 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/crunchy_uranium.json @@ -0,0 +1,34 @@ +{ + "parent": "createnuclear:yellowcake", + "criteria": { + "0": { + "conditions": { + "item": { + "items": "createnuclear:yellowcake" + } + }, + "trigger": "minecraft:consume_item" + } + }, + "display": { + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.crunchy_uranium.desc" + }, + "frame": "goal", + "hidden": true, + "icon": { + "count": 1, + "id": "createnuclear:yellowcake" + }, + "title": { + "translate": "advancement.createnuclear.crunchy_uranium" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/cryogenic_baptism.json b/src/generated/resources/data/createnuclear/advancement/cryogenic_baptism.json new file mode 100644 index 0000000..df06cf9 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/cryogenic_baptism.json @@ -0,0 +1,29 @@ +{ + "parent": "createnuclear:absolute_zero", + "criteria": { + "0": { + "trigger": "createnuclear:cryogenic_baptism_builtin" + } + }, + "display": { + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.cryogenic_baptism.desc" + }, + "frame": "goal", + "hidden": true, + "icon": { + "count": 1, + "id": "createnuclear:nitrogen_bucket" + }, + "title": { + "translate": "advancement.createnuclear.cryogenic_baptism" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/dye_anti_radiation_armor.json b/src/generated/resources/data/createnuclear/advancement/dye_anti_radiation_armor.json index 95a8c47..34b8e47 100644 --- a/src/generated/resources/data/createnuclear/advancement/dye_anti_radiation_armor.json +++ b/src/generated/resources/data/createnuclear/advancement/dye_anti_radiation_armor.json @@ -2,34 +2,7 @@ "parent": "createnuclear:anti_radiation_armor", "criteria": { "0": { - "conditions": { - "items": [ - { - "items": "#createnuclear:anti_radiation_helmet_dye" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "1": { - "conditions": { - "items": [ - { - "items": "#createnuclear:anti_radiation_chestplate_dye" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "2": { - "conditions": { - "items": [ - { - "items": "#createnuclear:anti_radiation_leggings_dye" - } - ] - }, - "trigger": "minecraft:inventory_changed" + "trigger": "createnuclear:dye_anti_radiation_armor_builtin" } }, "display": { @@ -40,7 +13,7 @@ }, "icon": { "count": 1, - "id": "createnuclear:red_anti_radiation_helmet" + "id": "createnuclear:default_anti_radiation_helmet" }, "title": { "translate": "advancement.createnuclear.dye_anti_radiation_armor" @@ -49,12 +22,6 @@ "requirements": [ [ "0" - ], - [ - "1" - ], - [ - "2" ] ], "sends_telemetry_event": true diff --git a/src/generated/resources/data/createnuclear/advancement/feeding_the_reactor.json b/src/generated/resources/data/createnuclear/advancement/feeding_the_reactor.json new file mode 100644 index 0000000..ead9f93 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/feeding_the_reactor.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:reactor_casing", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:reactor_rod_input" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.feeding_the_reactor.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:reactor_rod_input" + }, + "title": { + "translate": "advancement.createnuclear.feeding_the_reactor" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/fueling_the_reactor.json b/src/generated/resources/data/createnuclear/advancement/fueling_the_reactor.json new file mode 100644 index 0000000..3fa8371 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/fueling_the_reactor.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:feeding_the_reactor", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:reactor_fluid_input" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.fueling_the_reactor.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:reactor_fluid_input" + }, + "title": { + "translate": "advancement.createnuclear.fueling_the_reactor" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/full_anti_radiation_armor.json b/src/generated/resources/data/createnuclear/advancement/full_anti_radiation_armor.json deleted file mode 100644 index ce713d5..0000000 --- a/src/generated/resources/data/createnuclear/advancement/full_anti_radiation_armor.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "parent": "createnuclear:anti_radiation_armor", - "criteria": { - "0": { - "trigger": "create:full_anti_radiation_armor_builtin" - } - }, - "display": { - "announce_to_chat": false, - "description": { - "color": "#DBA213", - "translate": "advancement.createnuclear.full_anti_radiation_armor.desc" - }, - "icon": { - "count": 1, - "id": "createnuclear:white_anti_radiation_chestplate" - }, - "title": { - "translate": "advancement.createnuclear.full_anti_radiation_armor" - } - }, - "requirements": [ - [ - "0" - ] - ], - "sends_telemetry_event": true -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/getting_concentrated.json b/src/generated/resources/data/createnuclear/advancement/getting_concentrated.json new file mode 100644 index 0000000..92fedc6 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/getting_concentrated.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:chemistry_101", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:nitrogen_concentrate" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.getting_concentrated.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:nitrogen_concentrate" + }, + "title": { + "translate": "advancement.createnuclear.getting_concentrated" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/no_time_to_die.json b/src/generated/resources/data/createnuclear/advancement/no_time_to_die.json new file mode 100644 index 0000000..16cbcd5 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/no_time_to_die.json @@ -0,0 +1,28 @@ +{ + "parent": "createnuclear:reactor_controller", + "criteria": { + "0": { + "trigger": "createnuclear:no_time_to_die_builtin" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.no_time_to_die.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:autunite" + }, + "title": { + "translate": "advancement.createnuclear.no_time_to_die" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/raw_thorium.json b/src/generated/resources/data/createnuclear/advancement/raw_thorium.json new file mode 100644 index 0000000..c8f9146 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/raw_thorium.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:root", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:raw_thorium" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.raw_thorium.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:raw_thorium" + }, + "title": { + "translate": "advancement.createnuclear.raw_thorium" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/reactor_cooler.json b/src/generated/resources/data/createnuclear/advancement/reactor_cooler.json index 57a9c71..1b1a6b5 100644 --- a/src/generated/resources/data/createnuclear/advancement/reactor_cooler.json +++ b/src/generated/resources/data/createnuclear/advancement/reactor_cooler.json @@ -1,5 +1,5 @@ { - "parent": "createnuclear:reactor_casing", + "parent": "createnuclear:reactor_core", "criteria": { "0": { "conditions": { diff --git a/src/generated/resources/data/createnuclear/advancement/reactor_frame.json b/src/generated/resources/data/createnuclear/advancement/reactor_frame.json index 12d16ce..3621aff 100644 --- a/src/generated/resources/data/createnuclear/advancement/reactor_frame.json +++ b/src/generated/resources/data/createnuclear/advancement/reactor_frame.json @@ -1,5 +1,5 @@ { - "parent": "createnuclear:reactor_casing", + "parent": "createnuclear:reactor_cooler", "criteria": { "0": { "conditions": { diff --git a/src/generated/resources/data/createnuclear/advancement/reactor_input.json b/src/generated/resources/data/createnuclear/advancement/reactor_input.json deleted file mode 100644 index 15eaae0..0000000 --- a/src/generated/resources/data/createnuclear/advancement/reactor_input.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "createnuclear:reactor_casing", - "criteria": { - "0": { - "conditions": { - "items": [ - { - "items": "createnuclear:reactor_input" - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "display": { - "announce_to_chat": false, - "description": { - "color": "#DBA213", - "translate": "advancement.createnuclear.reactor_input.desc" - }, - "icon": { - "count": 1, - "id": "createnuclear:reactor_input" - }, - "title": { - "translate": "advancement.createnuclear.reactor_input" - } - }, - "requirements": [ - [ - "0" - ] - ], - "sends_telemetry_event": true -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/reactor_output.json b/src/generated/resources/data/createnuclear/advancement/reactor_output.json deleted file mode 100644 index 172846c..0000000 --- a/src/generated/resources/data/createnuclear/advancement/reactor_output.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parent": "createnuclear:reactor_casing", - "criteria": { - "0": { - "conditions": { - "items": [ - { - "items": "createnuclear:reactor_output" - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "display": { - "announce_to_chat": false, - "description": { - "color": "#DBA213", - "translate": "advancement.createnuclear.reactor_output.desc" - }, - "icon": { - "count": 1, - "id": "createnuclear:reactor_output" - }, - "title": { - "translate": "advancement.createnuclear.reactor_output" - } - }, - "requirements": [ - [ - "0" - ] - ], - "sends_telemetry_event": true -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/brewing/crafting/reinforced_glass_bottle.json b/src/generated/resources/data/createnuclear/advancement/recipes/brewing/crafting/reinforced_glass_bottle.json new file mode 100644 index 0000000..eaddfbe --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/brewing/crafting/reinforced_glass_bottle.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_reinforced_glass": { + "conditions": { + "items": [ + { + "items": "createnuclear:reinforced_glass" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/reinforced_glass_bottle" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_reinforced_glass" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/reinforced_glass_bottle" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/anti_radiation_boots.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/anti_radiation_boots.json deleted file mode 100644 index 672414f..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/anti_radiation_boots.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/anti_radiation_boots" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/anti_radiation_boots" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_chestplate.json deleted file mode 100644 index 9fbc4bc..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/black_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/black_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_helmet.json deleted file mode 100644 index 3c2b007..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/black_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/black_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_leggings.json deleted file mode 100644 index 07cc94d..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/black_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/black_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/black_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_chestplate.json deleted file mode 100644 index 6b9324c..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/blue_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/blue_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_helmet.json deleted file mode 100644 index 9aef456..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/blue_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/blue_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_leggings.json deleted file mode 100644 index 418d544..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/blue_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/blue_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/blue_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_chestplate.json deleted file mode 100644 index 91fe259..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/brown_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/brown_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_helmet.json deleted file mode 100644 index 31a9a5a..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/brown_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/brown_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_leggings.json deleted file mode 100644 index 26308a7..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/brown_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/brown_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/brown_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_chestplate.json deleted file mode 100644 index db03955..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/cyan_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/cyan_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_helmet.json deleted file mode 100644 index e8433a8..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/cyan_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/cyan_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_leggings.json deleted file mode 100644 index 16977ad..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/cyan_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/cyan_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/cyan_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_boots.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_boots.json new file mode 100644 index 0000000..fcb585a --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_boots.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/items/armors/default_anti_radiation_boots" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/items/armors/default_anti_radiation_boots" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_chestplate.json new file mode 100644 index 0000000..0a7e49d --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_chestplate.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/items/armors/default_anti_radiation_chestplate" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/items/armors/default_anti_radiation_chestplate" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_helmet.json new file mode 100644 index 0000000..8ea9092 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_helmet.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/items/armors/default_anti_radiation_helmet" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/items/armors/default_anti_radiation_helmet" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_leggings.json new file mode 100644 index 0000000..9b9dfdc --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/default_anti_radiation_leggings.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/items/armors/default_anti_radiation_leggings" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/items/armors/default_anti_radiation_leggings" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_chestplate.json deleted file mode 100644 index 96b0e80..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/gray_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/gray_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_helmet.json deleted file mode 100644 index 286133e..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/gray_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/gray_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_leggings.json deleted file mode 100644 index 2468b69..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/gray_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/gray_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/gray_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_chestplate.json deleted file mode 100644 index caa6c87..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/green_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/green_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_helmet.json deleted file mode 100644 index 4753792..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/green_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/green_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_leggings.json deleted file mode 100644 index 6a18b88..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/green_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/green_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/green_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_chestplate.json deleted file mode 100644 index 3fab0ff..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/light_blue_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/light_blue_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_helmet.json deleted file mode 100644 index 1e45b10..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/light_blue_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/light_blue_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_leggings.json deleted file mode 100644 index 19439a7..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_blue_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/light_blue_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/light_blue_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_chestplate.json deleted file mode 100644 index d91df61..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/light_gray_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/light_gray_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_helmet.json deleted file mode 100644 index 3754f1e..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/light_gray_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/light_gray_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_leggings.json deleted file mode 100644 index ba33967..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/light_gray_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/light_gray_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/light_gray_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_chestplate.json deleted file mode 100644 index e663e27..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/lime_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/lime_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_helmet.json deleted file mode 100644 index 8ad7da8..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/lime_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/lime_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_leggings.json deleted file mode 100644 index 5e21e72..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/lime_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/lime_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/lime_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_chestplate.json deleted file mode 100644 index 2315e7e..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/magenta_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/magenta_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_helmet.json deleted file mode 100644 index eb89e45..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/magenta_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/magenta_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_leggings.json deleted file mode 100644 index f079d14..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/magenta_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/magenta_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/magenta_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_chestplate.json deleted file mode 100644 index b988537..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/orange_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/orange_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_helmet.json deleted file mode 100644 index e5de4e6..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/orange_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/orange_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_leggings.json deleted file mode 100644 index 35234c6..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/orange_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/orange_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/orange_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_chestplate.json deleted file mode 100644 index 1c901fc..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/pink_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/pink_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_helmet.json deleted file mode 100644 index 793054c..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/pink_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/pink_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_leggings.json deleted file mode 100644 index 91984bf..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/pink_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/pink_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/pink_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_chestplate.json deleted file mode 100644 index 86f0d32..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/purple_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/purple_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_helmet.json deleted file mode 100644 index ff53e68..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/purple_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/purple_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_leggings.json deleted file mode 100644 index d3f6b55..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/purple_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/purple_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/purple_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_chestplate.json deleted file mode 100644 index fefd1ca..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/red_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/red_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_helmet.json deleted file mode 100644 index 4a66dc7..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/red_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/red_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_leggings.json deleted file mode 100644 index 0aaae00..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/red_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/red_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/red_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_chestplate.json deleted file mode 100644 index 2708d03..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/white_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/white_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_helmet.json deleted file mode 100644 index c6ce654..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/white_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/white_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_leggings.json deleted file mode 100644 index 0c51869..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/white_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/white_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/white_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_chestplate.json deleted file mode 100644 index 0d86760..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_chestplate.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/yellow_anti_radiation_chestplate" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/yellow_anti_radiation_chestplate" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_helmet.json deleted file mode 100644 index 4e6973a..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_helmet.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/yellow_anti_radiation_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/yellow_anti_radiation_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_leggings.json deleted file mode 100644 index 6e0b655..0000000 --- a/src/generated/resources/data/createnuclear/advancement/recipes/combat/crafting/items/armors/yellow_anti_radiation_leggings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_cloth": { - "conditions": { - "items": [ - { - "items": "#createnuclear:cloth" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "createnuclear:crafting/items/armors/yellow_anti_radiation_leggings" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_the_recipe", - "has_cloth" - ] - ], - "rewards": { - "recipes": [ - "createnuclear:crafting/items/armors/yellow_anti_radiation_leggings" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_black.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_black.json new file mode 100644 index 0000000..3e107df --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_black.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_black" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_black" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_blue.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_blue.json new file mode 100644 index 0000000..9027147 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_blue.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_blue" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_blue" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_brown.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_brown.json new file mode 100644 index 0000000..0edecac --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_brown.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_brown" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_brown" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_cyan.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_cyan.json new file mode 100644 index 0000000..ec016e2 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_cyan.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_cyan" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_cyan" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_gray.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_gray.json new file mode 100644 index 0000000..4db024f --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_gray.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_gray" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_gray" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_green.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_green.json new file mode 100644 index 0000000..e3e4d9d --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_green.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_green" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_green" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_light_blue.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_light_blue.json new file mode 100644 index 0000000..ae80c55 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_light_blue.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_light_blue" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_light_blue" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_light_gray.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_light_gray.json new file mode 100644 index 0000000..46dc188 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_light_gray.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_light_gray" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_light_gray" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_lime.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_lime.json new file mode 100644 index 0000000..e65c27c --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_lime.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_lime" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_lime" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_magenta.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_magenta.json new file mode 100644 index 0000000..822dac7 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_magenta.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_magenta" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_magenta" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_orange.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_orange.json new file mode 100644 index 0000000..4abbf58 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_orange.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_orange" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_orange" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_pink.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_pink.json new file mode 100644 index 0000000..8e8e6c3 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_pink.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_pink" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_pink" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_purple.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_purple.json new file mode 100644 index 0000000..37c6d94 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_purple.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_purple" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_purple" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_red.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_red.json new file mode 100644 index 0000000..e231597 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_red.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_red" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_red" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_white.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_white.json new file mode 100644 index 0000000..c7cc155 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_white.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_white" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_white" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_yellow.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_yellow.json new file mode 100644 index 0000000..5c91206 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_boots_yellow.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_boots_yellow" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_boots_yellow" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_black.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_black.json new file mode 100644 index 0000000..ed12726 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_black.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_black" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_black" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_blue.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_blue.json new file mode 100644 index 0000000..506387d --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_blue.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_blue" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_blue" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_brown.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_brown.json new file mode 100644 index 0000000..99b4b4e --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_brown.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_brown" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_brown" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_cyan.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_cyan.json new file mode 100644 index 0000000..ccb3a49 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_cyan.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_cyan" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_cyan" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_gray.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_gray.json new file mode 100644 index 0000000..eb552c5 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_gray.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_gray" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_gray" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_green.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_green.json new file mode 100644 index 0000000..b8d1bec --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_green.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_green" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_green" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_light_blue.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_light_blue.json new file mode 100644 index 0000000..8f55b1c --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_light_blue.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_light_blue" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_light_blue" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_light_gray.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_light_gray.json new file mode 100644 index 0000000..6b0efe2 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_light_gray.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_light_gray" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_light_gray" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_lime.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_lime.json new file mode 100644 index 0000000..6bf6580 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_lime.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_lime" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_lime" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_magenta.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_magenta.json new file mode 100644 index 0000000..5b1f4d0 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_magenta.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_magenta" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_magenta" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_orange.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_orange.json new file mode 100644 index 0000000..ff59061 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_orange.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_orange" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_orange" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_pink.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_pink.json new file mode 100644 index 0000000..95c2cd5 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_pink.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_pink" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_pink" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_purple.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_purple.json new file mode 100644 index 0000000..2022e5e --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_purple.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_purple" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_purple" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_red.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_red.json new file mode 100644 index 0000000..d8d0b25 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_red.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_red" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_red" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_white.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_white.json new file mode 100644 index 0000000..ec2b230 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_white.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_white" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_white" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_yellow.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_yellow.json new file mode 100644 index 0000000..629b604 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_chestplate_yellow.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_chestplate_yellow" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_chestplate_yellow" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_black.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_black.json new file mode 100644 index 0000000..ea044e3 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_black.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_black" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_black" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_blue.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_blue.json new file mode 100644 index 0000000..40d9b89 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_blue.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_blue" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_blue" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_brown.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_brown.json new file mode 100644 index 0000000..e70d134 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_brown.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_brown" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_brown" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_cyan.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_cyan.json new file mode 100644 index 0000000..30f8a36 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_cyan.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_cyan" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_cyan" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_gray.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_gray.json new file mode 100644 index 0000000..09b446b --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_gray.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_gray" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_gray" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_green.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_green.json new file mode 100644 index 0000000..8223cde --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_green.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_green" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_green" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_light_blue.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_light_blue.json new file mode 100644 index 0000000..bab9917 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_light_blue.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_light_blue" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_light_blue" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_light_gray.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_light_gray.json new file mode 100644 index 0000000..00f45d8 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_light_gray.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_light_gray" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_light_gray" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_lime.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_lime.json new file mode 100644 index 0000000..9975710 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_lime.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_lime" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_lime" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_magenta.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_magenta.json new file mode 100644 index 0000000..492618d --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_magenta.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_magenta" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_magenta" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_orange.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_orange.json new file mode 100644 index 0000000..6282fff --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_orange.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_orange" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_orange" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_pink.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_pink.json new file mode 100644 index 0000000..bc9d71f --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_pink.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_pink" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_pink" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_purple.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_purple.json new file mode 100644 index 0000000..9038c55 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_purple.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_purple" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_purple" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_red.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_red.json new file mode 100644 index 0000000..697292e --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_red.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_red" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_red" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_white.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_white.json new file mode 100644 index 0000000..2e2a1c7 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_white.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_white" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_white" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_yellow.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_yellow.json new file mode 100644 index 0000000..6adc183 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_helmet_yellow.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_helmet_yellow" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_helmet_yellow" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_black.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_black.json new file mode 100644 index 0000000..a394e81 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_black.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_black" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_black" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_blue.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_blue.json new file mode 100644 index 0000000..bce64a0 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_blue.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_blue" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_blue" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_brown.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_brown.json new file mode 100644 index 0000000..84c286d --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_brown.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_brown" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_brown" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_cyan.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_cyan.json new file mode 100644 index 0000000..6e69c67 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_cyan.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_cyan" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_cyan" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_gray.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_gray.json new file mode 100644 index 0000000..4c955b3 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_gray.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_gray" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_gray" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_green.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_green.json new file mode 100644 index 0000000..f3ffc50 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_green.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_green" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_green" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_light_blue.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_light_blue.json new file mode 100644 index 0000000..f36db0d --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_light_blue.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_light_blue" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_light_blue" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_light_gray.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_light_gray.json new file mode 100644 index 0000000..76dae3d --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_light_gray.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_light_gray" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_light_gray" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_lime.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_lime.json new file mode 100644 index 0000000..ac6e3da --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_lime.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_lime" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_lime" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_magenta.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_magenta.json new file mode 100644 index 0000000..f55417c --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_magenta.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_magenta" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_magenta" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_orange.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_orange.json new file mode 100644 index 0000000..a130a35 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_orange.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_orange" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_orange" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_pink.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_pink.json new file mode 100644 index 0000000..b25c644 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_pink.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_pink" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_pink" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_purple.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_purple.json new file mode 100644 index 0000000..fa69fcf --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_purple.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_purple" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_purple" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_red.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_red.json new file mode 100644 index 0000000..c588c62 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_red.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_red" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_red" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_white.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_white.json new file mode 100644 index 0000000..c96a916 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_white.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_white" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_white" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_yellow.json b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_yellow.json new file mode 100644 index 0000000..3cbb7db --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/combat/smithing/default_anti_radiation_leggings_yellow.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_cloth": { + "conditions": { + "items": [ + { + "items": "#createnuclear:cloth" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smithing/default_anti_radiation_leggings_yellow" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_cloth" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smithing/default_anti_radiation_leggings_yellow" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/decorations/crafting/raw/raw_thorium_block.json b/src/generated/resources/data/createnuclear/advancement/recipes/decorations/crafting/raw/raw_thorium_block.json new file mode 100644 index 0000000..dc812e6 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/decorations/crafting/raw/raw_thorium_block.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_raw_materials_thorium": { + "conditions": { + "items": [ + { + "items": "#c:raw_materials/thorium" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/raw/raw_thorium_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_raw_materials_thorium" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/raw/raw_thorium_block" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/lead_ingot_for_lead_ore.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/lead_ingot_for_lead_ore.json index 83d5b76..103a733 100644 --- a/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/lead_ingot_for_lead_ore.json +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/lead_ingot_for_lead_ore.json @@ -5,7 +5,7 @@ "conditions": { "items": [ { - "items": "#createnuclear:lead_ores" + "items": "#c:ores/lead" } ] }, diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/nitrogen_concentrate_for_nitrogen_concentrate.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/nitrogen_concentrate_for_nitrogen_concentrate.json new file mode 100644 index 0000000..21ae941 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/nitrogen_concentrate_for_nitrogen_concentrate.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": "createnuclear:nitrate" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:blasting/nitrogen_concentrate_for_nitrogen_concentrate" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_item" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:blasting/nitrogen_concentrate_for_nitrogen_concentrate" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/raw_uranium_for_uranium_ore.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/raw_uranium_for_uranium_ore.json index e4a0b81..6df4a45 100644 --- a/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/raw_uranium_for_uranium_ore.json +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/blasting/raw_uranium_for_uranium_ore.json @@ -5,7 +5,7 @@ "conditions": { "items": [ { - "items": "#createnuclear:uranium_ores" + "items": "#c:ores/uranium" } ] }, diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/biome_irradiation_extractor.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/biome_irradiation_extractor.json new file mode 100644 index 0000000..d03efad --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/biome_irradiation_extractor.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_reinforced_glass_bottle": { + "conditions": { + "items": [ + { + "items": "createnuclear:reinforced_glass_bottle" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/biome_irradiation_extractor" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_reinforced_glass_bottle" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/biome_irradiation_extractor" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_block_from_compacting.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_block_from_compacting.json new file mode 100644 index 0000000..b76e0d4 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_block_from_compacting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": "createnuclear:thorium_ingot" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/crafting/thorium_block_from_compacting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_item" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/crafting/thorium_block_from_compacting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_ingot_from_compacting.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_ingot_from_compacting.json new file mode 100644 index 0000000..0f67f37 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_ingot_from_compacting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": "createnuclear:thorium_nugget" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/crafting/thorium_ingot_from_compacting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_item" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/crafting/thorium_ingot_from_compacting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_ingot_from_decompacting.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_ingot_from_decompacting.json new file mode 100644 index 0000000..ba11dad --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_ingot_from_decompacting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": "createnuclear:thorium_block" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/crafting/thorium_ingot_from_decompacting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_item" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/crafting/thorium_ingot_from_decompacting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_nugget_from_decompacting.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_nugget_from_decompacting.json new file mode 100644 index 0000000..145c37d --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/crafting/thorium_nugget_from_decompacting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": "createnuclear:thorium_ingot" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/crafting/thorium_nugget_from_decompacting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_item" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/crafting/thorium_nugget_from_decompacting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/raw_thorium_from_decompacting.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/raw_thorium_from_decompacting.json new file mode 100644 index 0000000..2c835fe --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/raw_thorium_from_decompacting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_storage_blocks_raw_thorium": { + "conditions": { + "items": [ + { + "items": "#c:storage_blocks/raw_thorium" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/raw_thorium_from_decompacting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_storage_blocks_raw_thorium" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/raw_thorium_from_decompacting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/thorium_ingot_from_decompacting.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/thorium_ingot_from_decompacting.json new file mode 100644 index 0000000..532741f --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/thorium_ingot_from_decompacting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_storage_blocks_thorium": { + "conditions": { + "items": [ + { + "items": "#c:storage_blocks/thorium" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/thorium_ingot_from_decompacting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_storage_blocks_thorium" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/thorium_ingot_from_decompacting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/thorium_nugget_from_decompacting.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/thorium_nugget_from_decompacting.json new file mode 100644 index 0000000..a70570e --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/crafting/thorium_nugget_from_decompacting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_storage_blocks_steel_nugget": { + "conditions": { + "items": [ + { + "items": "#c:ingots/thorium" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:crafting/thorium_nugget_from_decompacting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_storage_blocks_steel_nugget" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:crafting/thorium_nugget_from_decompacting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/lead_ingot_for_lead_ore.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/lead_ingot_for_lead_ore.json index 6f8e7c1..9372e53 100644 --- a/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/lead_ingot_for_lead_ore.json +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/lead_ingot_for_lead_ore.json @@ -5,7 +5,7 @@ "conditions": { "items": [ { - "items": "#createnuclear:lead_ores" + "items": "#c:ores/lead" } ] }, diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/nitrogen_concentrate_for_nitrogen_concentrate.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/nitrogen_concentrate_for_nitrogen_concentrate.json new file mode 100644 index 0000000..e1208f4 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/nitrogen_concentrate_for_nitrogen_concentrate.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": "createnuclear:nitrate" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "createnuclear:smelting/nitrogen_concentrate_for_nitrogen_concentrate" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_item" + ] + ], + "rewards": { + "recipes": [ + "createnuclear:smelting/nitrogen_concentrate_for_nitrogen_concentrate" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/raw_uranium_for_uranium_ore.json b/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/raw_uranium_for_uranium_ore.json index 5fbe4f6..e44a7e3 100644 --- a/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/raw_uranium_for_uranium_ore.json +++ b/src/generated/resources/data/createnuclear/advancement/recipes/misc/smelting/raw_uranium_for_uranium_ore.json @@ -5,7 +5,7 @@ "conditions": { "items": [ { - "items": "#createnuclear:uranium_ores" + "items": "#c:ores/uranium" } ] }, diff --git a/src/generated/resources/data/createnuclear/advancement/root.json b/src/generated/resources/data/createnuclear/advancement/root.json index a12c7d3..b1ad3fb 100644 --- a/src/generated/resources/data/createnuclear/advancement/root.json +++ b/src/generated/resources/data/createnuclear/advancement/root.json @@ -6,7 +6,7 @@ }, "display": { "announce_to_chat": false, - "background": "createnuclear:textures/block/steel_block.png", + "background": "createnuclear:textures/gui/advancements/backgrounds/background_advancement.png", "description": { "color": "#DBA213", "translate": "advancement.createnuclear.root.desc" diff --git a/src/generated/resources/data/createnuclear/advancement/silence_the_core.json b/src/generated/resources/data/createnuclear/advancement/silence_the_core.json new file mode 100644 index 0000000..61cca34 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/silence_the_core.json @@ -0,0 +1,28 @@ +{ + "parent": "createnuclear:reactor_casing", + "criteria": { + "0": { + "trigger": "createnuclear:silence_the_core_builtin" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.silence_the_core.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:reactor_alarm" + }, + "title": { + "translate": "advancement.createnuclear.silence_the_core" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/t1.json b/src/generated/resources/data/createnuclear/advancement/t1.json new file mode 100644 index 0000000..1a74cc7 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/t1.json @@ -0,0 +1,28 @@ +{ + "parent": "createnuclear:reactor_controller", + "criteria": { + "0": { + "trigger": "createnuclear:t1_builtin" + } + }, + "display": { + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.t1.desc" + }, + "frame": "goal", + "icon": { + "count": 1, + "id": "createnuclear:reactor_controller" + }, + "title": { + "translate": "advancement.createnuclear.t1" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/t2.json b/src/generated/resources/data/createnuclear/advancement/t2.json new file mode 100644 index 0000000..443e0b6 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/t2.json @@ -0,0 +1,28 @@ +{ + "parent": "createnuclear:t1", + "criteria": { + "0": { + "trigger": "createnuclear:t2_builtin" + } + }, + "display": { + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.t2.desc" + }, + "frame": "goal", + "icon": { + "count": 1, + "id": "createnuclear:reactor_controller" + }, + "title": { + "translate": "advancement.createnuclear.t2" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/t3.json b/src/generated/resources/data/createnuclear/advancement/t3.json new file mode 100644 index 0000000..004019c --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/t3.json @@ -0,0 +1,28 @@ +{ + "parent": "createnuclear:t2", + "criteria": { + "0": { + "trigger": "createnuclear:t3_builtin" + } + }, + "display": { + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.t3.desc" + }, + "frame": "goal", + "icon": { + "count": 1, + "id": "createnuclear:reactor_controller" + }, + "title": { + "translate": "advancement.createnuclear.t3" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/thorium_dust.json b/src/generated/resources/data/createnuclear/advancement/thorium_dust.json new file mode 100644 index 0000000..feba819 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/thorium_dust.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:raw_thorium", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:thorium_dust" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.thorium_dust.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:thorium_dust" + }, + "title": { + "translate": "advancement.createnuclear.thorium_dust" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/thorium_ingot.json b/src/generated/resources/data/createnuclear/advancement/thorium_ingot.json new file mode 100644 index 0000000..e392d00 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/thorium_ingot.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:thorium_liquid", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:thorium_ingot" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.thorium_ingot.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:thorium_ingot" + }, + "title": { + "translate": "advancement.createnuclear.thorium_ingot" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/thorium_liquid.json b/src/generated/resources/data/createnuclear/advancement/thorium_liquid.json new file mode 100644 index 0000000..74b87f1 --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/thorium_liquid.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:thorium_dust", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:thorium_bucket" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.thorium_liquid.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:thorium_bucket" + }, + "title": { + "translate": "advancement.createnuclear.thorium_liquid" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/thorium_rod.json b/src/generated/resources/data/createnuclear/advancement/thorium_rod.json new file mode 100644 index 0000000..0af4c5c --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/thorium_rod.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:thorium_ingot", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:thorium_rod" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.thorium_rod.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:thorium_rod" + }, + "title": { + "translate": "advancement.createnuclear.thorium_rod" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/advancement/unlimited_power.json b/src/generated/resources/data/createnuclear/advancement/unlimited_power.json new file mode 100644 index 0000000..6fedfdc --- /dev/null +++ b/src/generated/resources/data/createnuclear/advancement/unlimited_power.json @@ -0,0 +1,35 @@ +{ + "parent": "createnuclear:fueling_the_reactor", + "criteria": { + "0": { + "conditions": { + "items": [ + { + "items": "createnuclear:reactor_output" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "display": { + "announce_to_chat": false, + "description": { + "color": "#DBA213", + "translate": "advancement.createnuclear.unlimited_power.desc" + }, + "icon": { + "count": 1, + "id": "createnuclear:reactor_output" + }, + "title": { + "translate": "advancement.createnuclear.unlimited_power" + } + }, + "requirements": [ + [ + "0" + ] + ], + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/createnuclear/fluids/type/fallback.json b/src/generated/resources/data/createnuclear/createnuclear/fluids/type/fallback.json new file mode 100644 index 0000000..ea208e2 --- /dev/null +++ b/src/generated/resources/data/createnuclear/createnuclear/fluids/type/fallback.json @@ -0,0 +1,5 @@ +{ + "efficiency": -1, + "fluid": "minecraft:empty", + "maxHeat": -1 +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/createnuclear/fluids/type/nitrogen.json b/src/generated/resources/data/createnuclear/createnuclear/fluids/type/nitrogen.json new file mode 100644 index 0000000..62e15f9 --- /dev/null +++ b/src/generated/resources/data/createnuclear/createnuclear/fluids/type/nitrogen.json @@ -0,0 +1,5 @@ +{ + "efficiency": 100, + "fluid": "createnuclear:nitrogen", + "maxHeat": 8196 +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/createnuclear/fluids/type/water.json b/src/generated/resources/data/createnuclear/createnuclear/fluids/type/water.json new file mode 100644 index 0000000..5a3ff58 --- /dev/null +++ b/src/generated/resources/data/createnuclear/createnuclear/fluids/type/water.json @@ -0,0 +1,5 @@ +{ + "efficiency": 1000, + "fluid": "minecraft:water", + "maxHeat": 2048 +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/createnuclear/rods/type/fallback.json b/src/generated/resources/data/createnuclear/createnuclear/rods/type/fallback.json new file mode 100644 index 0000000..57c68b4 --- /dev/null +++ b/src/generated/resources/data/createnuclear/createnuclear/rods/type/fallback.json @@ -0,0 +1,7 @@ +{ + "type": "NONE", + "baseRodHeat": -1, + "item": "minecraft:air", + "proximityRodHeat": -1.0, + "rodTimer": -1 +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/damage_type/fan_radiation.json b/src/generated/resources/data/createnuclear/damage_type/fan_radiation.json new file mode 100644 index 0000000..1b8826c --- /dev/null +++ b/src/generated/resources/data/createnuclear/damage_type/fan_radiation.json @@ -0,0 +1,5 @@ +{ + "exhaustion": 0.1, + "message_id": "fan_radiation", + "scaling": "when_caused_by_living_non_player" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/damage_type/radiation.json b/src/generated/resources/data/createnuclear/damage_type/radiation.json new file mode 100644 index 0000000..3e35efa --- /dev/null +++ b/src/generated/resources/data/createnuclear/damage_type/radiation.json @@ -0,0 +1,5 @@ +{ + "exhaustion": 0.1, + "message_id": "radiation", + "scaling": "when_caused_by_living_non_player" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_lead_ore.json b/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_lead_ore.json index f31bd5b..0d05dcc 100644 --- a/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_lead_ore.json +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_lead_ore.json @@ -31,10 +31,22 @@ { "type": "minecraft:item", "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 4.0, + "min": 2.0 + }, + "function": "minecraft:set_count" + }, { "enchantment": "minecraft:fortune", - "formula": "minecraft:ore_drops", - "function": "minecraft:apply_bonus" + "formula": "minecraft:uniform_bonus_count", + "function": "minecraft:apply_bonus", + "parameters": { + "bonusMultiplier": 4 + } }, { "function": "minecraft:explosion_decay" diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_nitrate_ore.json b/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_nitrate_ore.json new file mode 100644 index 0000000..9eb39c4 --- /dev/null +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_nitrate_ore.json @@ -0,0 +1,52 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "predicates": { + "minecraft:enchantments": [ + { + "enchantments": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + } + ], + "name": "createnuclear:deepslate_nitrate_ore" + }, + { + "type": "minecraft:item", + "functions": [ + { + "enchantment": "minecraft:fortune", + "formula": "minecraft:ore_drops", + "function": "minecraft:apply_bonus" + }, + { + "function": "minecraft:explosion_decay" + } + ], + "name": "createnuclear:nitrate" + } + ] + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "createnuclear:blocks/deepslate_nitrate_ore" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_thorium_ore.json b/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_thorium_ore.json new file mode 100644 index 0000000..e501346 --- /dev/null +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_thorium_ore.json @@ -0,0 +1,64 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "predicates": { + "minecraft:enchantments": [ + { + "enchantments": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + } + ], + "name": "createnuclear:deepslate_thorium_ore" + }, + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 5.0, + "min": 2.0 + }, + "function": "minecraft:set_count" + }, + { + "enchantment": "minecraft:fortune", + "formula": "minecraft:uniform_bonus_count", + "function": "minecraft:apply_bonus", + "parameters": { + "bonusMultiplier": 5 + } + }, + { + "function": "minecraft:explosion_decay" + } + ], + "name": "createnuclear:raw_thorium" + } + ] + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "createnuclear:blocks/deepslate_thorium_ore" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_uranium_ore.json b/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_uranium_ore.json index cf36f3d..d1e9a24 100644 --- a/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_uranium_ore.json +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/deepslate_uranium_ore.json @@ -31,10 +31,22 @@ { "type": "minecraft:item", "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 4.0, + "min": 3.0 + }, + "function": "minecraft:set_count" + }, { "enchantment": "minecraft:fortune", - "formula": "minecraft:ore_drops", - "function": "minecraft:apply_bonus" + "formula": "minecraft:uniform_bonus_count", + "function": "minecraft:apply_bonus", + "parameters": { + "bonusMultiplier": 1 + } }, { "function": "minecraft:explosion_decay" diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/lead_ore.json b/src/generated/resources/data/createnuclear/loot_table/blocks/lead_ore.json index 062d288..d0b73b9 100644 --- a/src/generated/resources/data/createnuclear/loot_table/blocks/lead_ore.json +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/lead_ore.json @@ -31,10 +31,22 @@ { "type": "minecraft:item", "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 4.0, + "min": 2.0 + }, + "function": "minecraft:set_count" + }, { "enchantment": "minecraft:fortune", - "formula": "minecraft:ore_drops", - "function": "minecraft:apply_bonus" + "formula": "minecraft:uniform_bonus_count", + "function": "minecraft:apply_bonus", + "parameters": { + "bonusMultiplier": 4 + } }, { "function": "minecraft:explosion_decay" diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/nitrate_ore.json b/src/generated/resources/data/createnuclear/loot_table/blocks/nitrate_ore.json new file mode 100644 index 0000000..57142f7 --- /dev/null +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/nitrate_ore.json @@ -0,0 +1,52 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "predicates": { + "minecraft:enchantments": [ + { + "enchantments": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + } + ], + "name": "createnuclear:nitrate_ore" + }, + { + "type": "minecraft:item", + "functions": [ + { + "enchantment": "minecraft:fortune", + "formula": "minecraft:ore_drops", + "function": "minecraft:apply_bonus" + }, + { + "function": "minecraft:explosion_decay" + } + ], + "name": "createnuclear:nitrate" + } + ] + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "createnuclear:blocks/nitrate_ore" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/raw_thorium_block.json b/src/generated/resources/data/createnuclear/loot_table/blocks/raw_thorium_block.json new file mode 100644 index 0000000..cb40bb6 --- /dev/null +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/raw_thorium_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "createnuclear:raw_thorium_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "createnuclear:blocks/raw_thorium_block" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_alarm.json b/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_alarm.json new file mode 100644 index 0000000..3a46c7a --- /dev/null +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_alarm.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "createnuclear:reactor_alarm" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "createnuclear:blocks/reactor_alarm" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_fluid_input.json b/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_fluid_input.json new file mode 100644 index 0000000..6fb4edd --- /dev/null +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_fluid_input.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "createnuclear:reactor_fluid_input" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "createnuclear:blocks/reactor_fluid_input" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_input.json b/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_input.json deleted file mode 100644 index 12d0852..0000000 --- a/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_input.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:block", - "pools": [ - { - "bonus_rolls": 0.0, - "conditions": [ - { - "condition": "minecraft:survives_explosion" - } - ], - "entries": [ - { - "type": "minecraft:item", - "name": "createnuclear:reactor_input" - } - ], - "rolls": 1.0 - } - ], - "random_sequence": "createnuclear:blocks/reactor_input" -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_rod_input.json b/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_rod_input.json new file mode 100644 index 0000000..bc71169 --- /dev/null +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/reactor_rod_input.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "createnuclear:reactor_rod_input" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "createnuclear:blocks/reactor_rod_input" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/thorium_block.json b/src/generated/resources/data/createnuclear/loot_table/blocks/thorium_block.json new file mode 100644 index 0000000..346c868 --- /dev/null +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/thorium_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "createnuclear:thorium_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "createnuclear:blocks/thorium_block" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/thorium_ore.json b/src/generated/resources/data/createnuclear/loot_table/blocks/thorium_ore.json new file mode 100644 index 0000000..0cc491f --- /dev/null +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/thorium_ore.json @@ -0,0 +1,64 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "predicates": { + "minecraft:enchantments": [ + { + "enchantments": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + } + ], + "name": "createnuclear:thorium_ore" + }, + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 5.0, + "min": 2.0 + }, + "function": "minecraft:set_count" + }, + { + "enchantment": "minecraft:fortune", + "formula": "minecraft:uniform_bonus_count", + "function": "minecraft:apply_bonus", + "parameters": { + "bonusMultiplier": 5 + } + }, + { + "function": "minecraft:explosion_decay" + } + ], + "name": "createnuclear:raw_thorium" + } + ] + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "createnuclear:blocks/thorium_ore" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/loot_table/blocks/uranium_ore.json b/src/generated/resources/data/createnuclear/loot_table/blocks/uranium_ore.json index 20c8f32..a5befab 100644 --- a/src/generated/resources/data/createnuclear/loot_table/blocks/uranium_ore.json +++ b/src/generated/resources/data/createnuclear/loot_table/blocks/uranium_ore.json @@ -31,10 +31,22 @@ { "type": "minecraft:item", "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 4.0, + "min": 3.0 + }, + "function": "minecraft:set_count" + }, { "enchantment": "minecraft:fortune", - "formula": "minecraft:ore_drops", - "function": "minecraft:apply_bonus" + "formula": "minecraft:uniform_bonus_count", + "function": "minecraft:apply_bonus", + "parameters": { + "bonusMultiplier": 1 + } }, { "function": "minecraft:explosion_decay" diff --git a/src/generated/resources/data/createnuclear/loot_table/entities/irradiated_cow.json b/src/generated/resources/data/createnuclear/loot_table/entities/irradiated_cow.json new file mode 100644 index 0000000..43e6419 --- /dev/null +++ b/src/generated/resources/data/createnuclear/loot_table/entities/irradiated_cow.json @@ -0,0 +1,4 @@ +{ + "type": "minecraft:entity", + "random_sequence": "createnuclear:entities/irradiated_cow" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/neoforge/biome_modifier/nitrate_ore.json b/src/generated/resources/data/createnuclear/neoforge/biome_modifier/nitrate_ore.json new file mode 100644 index 0000000..8048785 --- /dev/null +++ b/src/generated/resources/data/createnuclear/neoforge/biome_modifier/nitrate_ore.json @@ -0,0 +1,6 @@ +{ + "type": "neoforge:add_features", + "biomes": "#minecraft:is_overworld", + "features": "createnuclear:nitrate_ore", + "step": "underground_ores" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/neoforge/biome_modifier/thorium_ore.json b/src/generated/resources/data/createnuclear/neoforge/biome_modifier/thorium_ore.json new file mode 100644 index 0000000..a615ba5 --- /dev/null +++ b/src/generated/resources/data/createnuclear/neoforge/biome_modifier/thorium_ore.json @@ -0,0 +1,6 @@ +{ + "type": "neoforge:add_features", + "biomes": "#minecraft:is_overworld", + "features": "createnuclear:thorium_ore", + "step": "underground_ores" +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/blasting/lead_ingot_for_lead_ore.json b/src/generated/resources/data/createnuclear/recipe/blasting/lead_ingot_for_lead_ore.json index 625464b..bcc1660 100644 --- a/src/generated/resources/data/createnuclear/recipe/blasting/lead_ingot_for_lead_ore.json +++ b/src/generated/resources/data/createnuclear/recipe/blasting/lead_ingot_for_lead_ore.json @@ -4,7 +4,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "tag": "createnuclear:lead_ores" + "tag": "c:ores/lead" }, "result": { "count": 1, diff --git a/src/generated/resources/data/createnuclear/recipe/blasting/nitrogen_concentrate_for_nitrogen_concentrate.json b/src/generated/resources/data/createnuclear/recipe/blasting/nitrogen_concentrate_for_nitrogen_concentrate.json new file mode 100644 index 0000000..ccf99fe --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/blasting/nitrogen_concentrate_for_nitrogen_concentrate.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:blasting", + "category": "misc", + "cookingtime": 100, + "experience": 0.1, + "ingredient": { + "item": "createnuclear:nitrate" + }, + "result": { + "count": 1, + "id": "createnuclear:nitrogen_concentrate" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/blasting/raw_uranium_for_uranium_ore.json b/src/generated/resources/data/createnuclear/recipe/blasting/raw_uranium_for_uranium_ore.json index 75339d6..db6aaa4 100644 --- a/src/generated/resources/data/createnuclear/recipe/blasting/raw_uranium_for_uranium_ore.json +++ b/src/generated/resources/data/createnuclear/recipe/blasting/raw_uranium_for_uranium_ore.json @@ -4,7 +4,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "tag": "createnuclear:uranium_ores" + "tag": "c:ores/uranium" }, "result": { "count": 1, diff --git a/src/generated/resources/data/createnuclear/recipe/compacting/thorium_fluid_to_thorium_ingot.json b/src/generated/resources/data/createnuclear/recipe/compacting/thorium_fluid_to_thorium_ingot.json new file mode 100644 index 0000000..ec07d10 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/compacting/thorium_fluid_to_thorium_ingot.json @@ -0,0 +1,15 @@ +{ + "type": "create:compacting", + "ingredients": [ + { + "type": "neoforge:tag", + "amount": 200, + "tag": "createnuclear:thorium" + } + ], + "results": [ + { + "id": "createnuclear:thorium_ingot" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/compacting/uranium_fluid_to_yellowcake.json b/src/generated/resources/data/createnuclear/recipe/compacting/uranium_fluid_to_yellowcake.json index b5f7a53..b9e9346 100644 --- a/src/generated/resources/data/createnuclear/recipe/compacting/uranium_fluid_to_yellowcake.json +++ b/src/generated/resources/data/createnuclear/recipe/compacting/uranium_fluid_to_yellowcake.json @@ -2,9 +2,9 @@ "type": "create:compacting", "ingredients": [ { - "type": "neoforge:single", + "type": "neoforge:tag", "amount": 100, - "fluid": "createnuclear:uranium" + "tag": "createnuclear:uranium" } ], "results": [ diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/biome_irradiation_extractor.json b/src/generated/resources/data/createnuclear/recipe/crafting/biome_irradiation_extractor.json new file mode 100644 index 0000000..9c0739f --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/biome_irradiation_extractor.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "B": { + "item": "createnuclear:reinforced_glass_bottle" + }, + "S": { + "item": "minecraft:nether_star" + } + }, + "pattern": [ + "BBB", + "BSB", + "BBB" + ], + "result": { + "count": 8, + "id": "createnuclear:biome_irradiation_extractor" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_block_from_compacting.json b/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_block_from_compacting.json new file mode 100644 index 0000000..592e29c --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_block_from_compacting.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "#": { + "tag": "c:ingots/thorium" + } + }, + "pattern": [ + "###", + "###", + "###" + ], + "result": { + "count": 1, + "id": "createnuclear:thorium_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_ingot_from_compacting.json b/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_ingot_from_compacting.json new file mode 100644 index 0000000..bdd91e6 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_ingot_from_compacting.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "#": { + "tag": "c:nuggets/thorium" + } + }, + "pattern": [ + "###", + "###", + "###" + ], + "result": { + "count": 1, + "id": "createnuclear:thorium_ingot" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_ingot_from_decompacting.json b/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_ingot_from_decompacting.json new file mode 100644 index 0000000..feb4e86 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_ingot_from_decompacting.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "tag": "c:storage_blocks/thorium" + } + ], + "result": { + "count": 9, + "id": "createnuclear:thorium_ingot" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_nugget_from_decompacting.json b/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_nugget_from_decompacting.json new file mode 100644 index 0000000..72fba21 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/crafting/thorium_nugget_from_decompacting.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "tag": "c:ingots/thorium" + } + ], + "result": { + "count": 9, + "id": "createnuclear:thorium_nugget" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/anti_radiation_boots.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/anti_radiation_boots.json deleted file mode 100644 index 0a5deb3..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/anti_radiation_boots.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:white_cloth" - } - }, - "pattern": [ - "Y Y", - "X X" - ], - "result": { - "count": 1, - "id": "createnuclear:anti_radiation_boots" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_chestplate.json deleted file mode 100644 index 0f771fa..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:black_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:black_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_helmet.json deleted file mode 100644 index 80a6f13..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:black_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:black_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_leggings.json deleted file mode 100644 index c7e7085..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/black_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:black_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:black_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_chestplate.json deleted file mode 100644 index a82e4d1..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:blue_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:blue_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_helmet.json deleted file mode 100644 index 76a11b9..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:blue_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:blue_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_leggings.json deleted file mode 100644 index 6b9d947..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/blue_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:blue_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:blue_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_chestplate.json deleted file mode 100644 index 7ceeb96..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:brown_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:brown_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_helmet.json deleted file mode 100644 index 9fe93e5..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:brown_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:brown_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_leggings.json deleted file mode 100644 index 2b7cac8..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/brown_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:brown_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:brown_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_chestplate.json deleted file mode 100644 index 7e4302d..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:cyan_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:cyan_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_helmet.json deleted file mode 100644 index 6ae907a..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:cyan_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:cyan_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_leggings.json deleted file mode 100644 index c3cfe37..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/cyan_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:cyan_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:cyan_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_boots.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_boots.json new file mode 100644 index 0000000..394ac11 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_boots.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "equipment", + "key": { + "X": { + "tag": "c:ingots/lead" + }, + "Y": { + "tag": "c:ingots/brass" + } + }, + "pattern": [ + "Y Y", + "X X" + ], + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_chestplate.json new file mode 100644 index 0000000..8714da5 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_chestplate.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "equipment", + "key": { + "X": { + "tag": "c:ingots/lead" + }, + "Y": { + "tag": "c:ingots/brass" + }, + "Z": { + "item": "createnuclear:graphite_rod" + } + }, + "pattern": [ + "Y Y", + "XXX", + "ZXZ" + ], + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_helmet.json new file mode 100644 index 0000000..0548efa --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_helmet.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "equipment", + "key": { + "X": { + "tag": "c:ingots/lead" + }, + "Y": { + "tag": "c:ingots/brass" + }, + "Z": { + "item": "createnuclear:reinforced_glass" + } + }, + "pattern": [ + "YXY", + "XZX" + ], + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_leggings.json new file mode 100644 index 0000000..4ea2dc9 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/default_anti_radiation_leggings.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "equipment", + "key": { + "X": { + "tag": "c:ingots/lead" + }, + "Y": { + "tag": "c:ingots/brass" + } + }, + "pattern": [ + "YXY", + "X X", + "Y Y" + ], + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_chestplate.json deleted file mode 100644 index d79bc68..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:gray_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:gray_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_helmet.json deleted file mode 100644 index f2677df..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:gray_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:gray_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_leggings.json deleted file mode 100644 index 2dee8ab..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/gray_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:gray_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:gray_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_chestplate.json deleted file mode 100644 index ddee34c..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:green_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:green_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_helmet.json deleted file mode 100644 index 5855881..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:green_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:green_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_leggings.json deleted file mode 100644 index 02ac402..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/green_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:green_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:green_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_chestplate.json deleted file mode 100644 index 9ca6fe1..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:light_blue_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:light_blue_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_helmet.json deleted file mode 100644 index 03fa729..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:light_blue_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:light_blue_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_leggings.json deleted file mode 100644 index 9a74315..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_blue_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:light_blue_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:light_blue_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_chestplate.json deleted file mode 100644 index e404fbb..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:light_gray_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:light_gray_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_helmet.json deleted file mode 100644 index 9b99fcd..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:light_gray_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:light_gray_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_leggings.json deleted file mode 100644 index c711980..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/light_gray_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:light_gray_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:light_gray_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_chestplate.json deleted file mode 100644 index 3cae8ae..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:lime_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:lime_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_helmet.json deleted file mode 100644 index a12b2d7..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:lime_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:lime_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_leggings.json deleted file mode 100644 index a56691d..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/lime_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:lime_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:lime_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_chestplate.json deleted file mode 100644 index a4aea06..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:magenta_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:magenta_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_helmet.json deleted file mode 100644 index 1ff8973..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:magenta_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:magenta_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_leggings.json deleted file mode 100644 index 692ee1a..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/magenta_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:magenta_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:magenta_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_chestplate.json deleted file mode 100644 index 91994b3..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:orange_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:orange_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_helmet.json deleted file mode 100644 index c3cf259..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:orange_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:orange_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_leggings.json deleted file mode 100644 index cdcfc43..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/orange_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:orange_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:orange_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_chestplate.json deleted file mode 100644 index a41d61d..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:pink_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:pink_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_helmet.json deleted file mode 100644 index dec799a..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:pink_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:pink_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_leggings.json deleted file mode 100644 index c4da4f6..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/pink_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:pink_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:pink_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_chestplate.json deleted file mode 100644 index 00ece9f..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:purple_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:purple_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_helmet.json deleted file mode 100644 index 712deaa..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:purple_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:purple_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_leggings.json deleted file mode 100644 index 486279b..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/purple_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:purple_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:purple_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_chestplate.json deleted file mode 100644 index 177865b..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:red_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:red_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_helmet.json deleted file mode 100644 index 1c0b40b..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:red_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:red_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_leggings.json deleted file mode 100644 index cedec83..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/red_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:red_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:red_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_chestplate.json deleted file mode 100644 index a757878..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:white_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:white_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_helmet.json deleted file mode 100644 index 61743f4..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:white_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:white_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_leggings.json deleted file mode 100644 index 0334109..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/white_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:white_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:white_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_chestplate.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_chestplate.json deleted file mode 100644 index 7cc04db..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_chestplate.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:yellow_cloth" - }, - "Z": { - "item": "createnuclear:graphite_rod" - } - }, - "pattern": [ - "Y Y", - "XXX", - "ZXZ" - ], - "result": { - "count": 1, - "id": "createnuclear:yellow_anti_radiation_chestplate" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_helmet.json deleted file mode 100644 index 04c5f96..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_helmet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:yellow_cloth" - }, - "Z": { - "item": "createnuclear:reinforced_glass" - } - }, - "pattern": [ - "YXY", - "XZX" - ], - "result": { - "count": 1, - "id": "createnuclear:yellow_anti_radiation_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_leggings.json b/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_leggings.json deleted file mode 100644 index 74bd4b0..0000000 --- a/src/generated/resources/data/createnuclear/recipe/crafting/items/armors/yellow_anti_radiation_leggings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "equipment", - "key": { - "X": { - "tag": "c:ingots/lead" - }, - "Y": { - "item": "createnuclear:yellow_cloth" - } - }, - "pattern": [ - "YXY", - "X X", - "Y Y" - ], - "result": { - "count": 1, - "id": "createnuclear:yellow_anti_radiation_leggings" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/raw/raw_thorium_block.json b/src/generated/resources/data/createnuclear/recipe/crafting/raw/raw_thorium_block.json new file mode 100644 index 0000000..6b72af0 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/raw/raw_thorium_block.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "R": { + "tag": "c:raw_materials/thorium" + } + }, + "pattern": [ + "RRR", + "RRR", + "RRR" + ], + "result": { + "count": 1, + "id": "createnuclear:raw_thorium_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/raw_thorium_from_decompacting.json b/src/generated/resources/data/createnuclear/recipe/crafting/raw_thorium_from_decompacting.json new file mode 100644 index 0000000..1e56d66 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/raw_thorium_from_decompacting.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "tag": "c:storage_blocks/raw_thorium" + } + ], + "result": { + "count": 9, + "id": "createnuclear:raw_thorium" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/reinforced_glass_bottle.json b/src/generated/resources/data/createnuclear/recipe/crafting/reinforced_glass_bottle.json new file mode 100644 index 0000000..3281c7c --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/reinforced_glass_bottle.json @@ -0,0 +1,17 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "G": { + "item": "createnuclear:reinforced_glass" + } + }, + "pattern": [ + "G G", + " G " + ], + "result": { + "count": 3, + "id": "createnuclear:reinforced_glass_bottle" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/thorium_ingot_from_decompacting.json b/src/generated/resources/data/createnuclear/recipe/crafting/thorium_ingot_from_decompacting.json new file mode 100644 index 0000000..feb4e86 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/thorium_ingot_from_decompacting.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "tag": "c:storage_blocks/thorium" + } + ], + "result": { + "count": 9, + "id": "createnuclear:thorium_ingot" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crafting/thorium_nugget_from_decompacting.json b/src/generated/resources/data/createnuclear/recipe/crafting/thorium_nugget_from_decompacting.json new file mode 100644 index 0000000..72fba21 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crafting/thorium_nugget_from_decompacting.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "tag": "c:ingots/thorium" + } + ], + "result": { + "count": 9, + "id": "createnuclear:thorium_nugget" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipe/crushing/granite.json b/src/generated/resources/data/createnuclear/recipe/crushing/granite.json similarity index 100% rename from src/generated/resources/data/create/recipe/crushing/granite.json rename to src/generated/resources/data/createnuclear/recipe/crushing/granite.json diff --git a/src/generated/resources/data/createnuclear/recipe/crushing/nitrate.json b/src/generated/resources/data/createnuclear/recipe/crushing/nitrate.json new file mode 100644 index 0000000..70870bd --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crushing/nitrate.json @@ -0,0 +1,19 @@ +{ + "type": "create:crushing", + "ingredients": [ + { + "tag": "create:stone_types/limestone" + } + ], + "processing_time": 250, + "results": [ + { + "chance": 0.6, + "id": "createnuclear:nitrate" + }, + { + "chance": 0.4, + "id": "createnuclear:lead_nugget" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipe/crushing/raw_copper.json b/src/generated/resources/data/createnuclear/recipe/crushing/raw_copper.json similarity index 100% rename from src/generated/resources/data/create/recipe/crushing/raw_copper.json rename to src/generated/resources/data/createnuclear/recipe/crushing/raw_copper.json diff --git a/src/generated/resources/data/createnuclear/recipe/crushing/raw_thorium.json b/src/generated/resources/data/createnuclear/recipe/crushing/raw_thorium.json new file mode 100644 index 0000000..1fe9213 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crushing/raw_thorium.json @@ -0,0 +1,19 @@ +{ + "type": "create:crushing", + "ingredients": [ + { + "item": "createnuclear:raw_thorium" + } + ], + "processing_time": 125, + "results": [ + { + "id": "createnuclear:thorium_dust" + }, + { + "chance": 0.5, + "count": 8, + "id": "createnuclear:thorium_dust" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/crushing/raw_thorium_block.json b/src/generated/resources/data/createnuclear/recipe/crushing/raw_thorium_block.json new file mode 100644 index 0000000..8fbe3e1 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/crushing/raw_thorium_block.json @@ -0,0 +1,20 @@ +{ + "type": "create:crushing", + "ingredients": [ + { + "item": "createnuclear:raw_thorium_block" + } + ], + "processing_time": 250, + "results": [ + { + "count": 9, + "id": "createnuclear:thorium_dust" + }, + { + "chance": 0.5, + "count": 72, + "id": "createnuclear:thorium_dust" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipe/crushing/raw_uranium_block.json b/src/generated/resources/data/createnuclear/recipe/crushing/raw_uranium_block.json similarity index 100% rename from src/generated/resources/data/create/recipe/crushing/raw_uranium_block.json rename to src/generated/resources/data/createnuclear/recipe/crushing/raw_uranium_block.json diff --git a/src/generated/resources/data/create/recipe/crushing/raw_zinc.json b/src/generated/resources/data/createnuclear/recipe/crushing/raw_zinc.json similarity index 100% rename from src/generated/resources/data/create/recipe/crushing/raw_zinc.json rename to src/generated/resources/data/createnuclear/recipe/crushing/raw_zinc.json diff --git a/src/generated/resources/data/createnuclear/recipe/deploying/reactor_fluid_input_from_fluid_pipe_and_reactor_casing.json b/src/generated/resources/data/createnuclear/recipe/deploying/reactor_fluid_input_from_fluid_pipe_and_reactor_casing.json new file mode 100644 index 0000000..59cf97a --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/deploying/reactor_fluid_input_from_fluid_pipe_and_reactor_casing.json @@ -0,0 +1,16 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "createnuclear:reactor_casing" + }, + { + "item": "create:fluid_pipe" + } + ], + "results": [ + { + "id": "createnuclear:reactor_fluid_input" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/item_application/reactor_output_from_shaft_and_reactor_casing.json b/src/generated/resources/data/createnuclear/recipe/deploying/reactor_output_from_shaft_and_reactor_casing.json similarity index 84% rename from src/generated/resources/data/createnuclear/recipe/item_application/reactor_output_from_shaft_and_reactor_casing.json rename to src/generated/resources/data/createnuclear/recipe/deploying/reactor_output_from_shaft_and_reactor_casing.json index 8a7ee3f..31a4ae0 100644 --- a/src/generated/resources/data/createnuclear/recipe/item_application/reactor_output_from_shaft_and_reactor_casing.json +++ b/src/generated/resources/data/createnuclear/recipe/deploying/reactor_output_from_shaft_and_reactor_casing.json @@ -1,5 +1,5 @@ { - "type": "create:item_application", + "type": "create:deploying", "ingredients": [ { "item": "createnuclear:reactor_casing" diff --git a/src/generated/resources/data/createnuclear/recipe/deploying/reactor_rod_input_from_hopper_and_reactor_casing.json b/src/generated/resources/data/createnuclear/recipe/deploying/reactor_rod_input_from_hopper_and_reactor_casing.json new file mode 100644 index 0000000..1c36012 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/deploying/reactor_rod_input_from_hopper_and_reactor_casing.json @@ -0,0 +1,16 @@ +{ + "type": "create:deploying", + "ingredients": [ + { + "item": "createnuclear:reactor_casing" + }, + { + "item": "minecraft:hopper" + } + ], + "results": [ + { + "id": "createnuclear:reactor_rod_input" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/item_application/reactor_input_from_hopper_and_reactor_casing.json b/src/generated/resources/data/createnuclear/recipe/item_application/reactor_input_from_hopper_and_reactor_casing.json deleted file mode 100644 index 4dfeca5..0000000 --- a/src/generated/resources/data/createnuclear/recipe/item_application/reactor_input_from_hopper_and_reactor_casing.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "type": "create:item_application", - "ingredients": [ - { - "item": "createnuclear:reactor_casing" - }, - { - "item": "minecraft:hopper" - } - ], - "results": [ - { - "id": "createnuclear:reactor_input" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/mechanical_crafting/reactor_alarm.json b/src/generated/resources/data/createnuclear/recipe/mechanical_crafting/reactor_alarm.json new file mode 100644 index 0000000..104a34d --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/mechanical_crafting/reactor_alarm.json @@ -0,0 +1,30 @@ +{ + "type": "create:mechanical_crafting", + "accept_mirrored": true, + "category": "misc", + "key": { + "C": { + "item": "createnuclear:reactor_casing" + }, + "L": { + "item": "minecraft:clock" + }, + "N": { + "item": "minecraft:note_block" + }, + "R": { + "item": "minecraft:repeater" + } + }, + "pattern": [ + "CCCCC", + "CNRNC", + "CRLRC", + "CNRNC", + "CCCCC" + ], + "result": { + "count": 1, + "id": "createnuclear:reactor_alarm" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/mechanical_crafting/reactor_frame.json b/src/generated/resources/data/createnuclear/recipe/mechanical_crafting/reactor_frame.json index b9bc0d0..9d329e4 100644 --- a/src/generated/resources/data/createnuclear/recipe/mechanical_crafting/reactor_frame.json +++ b/src/generated/resources/data/createnuclear/recipe/mechanical_crafting/reactor_frame.json @@ -4,7 +4,7 @@ "category": "misc", "key": { "B": { - "item": "createnuclear:uranium_bucket" + "item": "minecraft:bucket" }, "C": { "item": "createnuclear:reactor_casing" diff --git a/src/generated/resources/data/createnuclear/recipe/mechanical_crafting/thorium_rod.json b/src/generated/resources/data/createnuclear/recipe/mechanical_crafting/thorium_rod.json new file mode 100644 index 0000000..48127fd --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/mechanical_crafting/thorium_rod.json @@ -0,0 +1,21 @@ +{ + "type": "create:mechanical_crafting", + "accept_mirrored": true, + "category": "misc", + "key": { + "U": { + "item": "createnuclear:thorium_ingot" + } + }, + "pattern": [ + "U ", + " U ", + " U ", + " U ", + " U" + ], + "result": { + "count": 1, + "id": "createnuclear:thorium_rod" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/mixing/liquid_nitrogen.json b/src/generated/resources/data/createnuclear/recipe/mixing/liquid_nitrogen.json new file mode 100644 index 0000000..fbd6d3f --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/mixing/liquid_nitrogen.json @@ -0,0 +1,18 @@ +{ + "type": "create:mixing", + "ingredients": [ + { + "item": "createnuclear:cooled_nitrogen_concentrate" + }, + { + "item": "minecraft:ice" + } + ], + "processing_time": 20, + "results": [ + { + "amount": 100, + "id": "createnuclear:nitrogen" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/mixing/thorium_fluid.json b/src/generated/resources/data/createnuclear/recipe/mixing/thorium_fluid.json new file mode 100644 index 0000000..af86bfb --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/mixing/thorium_fluid.json @@ -0,0 +1,15 @@ +{ + "type": "create:mixing", + "heat_requirement": "heated", + "ingredients": [ + { + "tag": "c:dusts/thorium" + } + ], + "results": [ + { + "amount": 25, + "id": "createnuclear:thorium" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/black_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/black_cloth.json index 097630b..4ec4285 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/black_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/black_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + } + ], { "item": "minecraft:black_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/blue_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/blue_cloth.json index 5f95b13..4ece5ea 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/blue_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/blue_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:blue_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/brown_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/brown_cloth.json index 4a8f320..600c7c6 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/brown_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/brown_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:brown_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/cyan_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/cyan_cloth.json index 7fc0b45..ce9c190 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/cyan_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/cyan_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:cyan_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/gray_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/gray_cloth.json index 3b919c2..0ec0a48 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/gray_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/gray_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:gray_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/green_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/green_cloth.json index 19b995e..dfa373b 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/green_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/green_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:green_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/light_blue_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/light_blue_cloth.json index 900de82..e4d5478 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/light_blue_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/light_blue_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:light_blue_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/light_gray_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/light_gray_cloth.json index ca9dfae..321bccb 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/light_gray_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/light_gray_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:light_gray_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/lime_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/lime_cloth.json index 616808a..d5eacea 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/lime_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/lime_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:lime_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/magenta_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/magenta_cloth.json index 557b951..e1f172f 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/magenta_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/magenta_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:magenta_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/orange_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/orange_cloth.json index 6654caf..544b4f7 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/orange_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/orange_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:orange_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/pink_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/pink_cloth.json index 6dde92b..dcf88a6 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/pink_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/pink_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:pink_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/purple_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/purple_cloth.json index efebcca..dfc3877 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/purple_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/purple_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:purple_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/red_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/red_cloth.json index ac90ce6..9eaecec 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/red_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/red_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:red_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/white_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/white_cloth.json index 8bc5688..6e503d6 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/white_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/white_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:yellow_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:white_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/yellow_cloth.json b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/yellow_cloth.json index 7c0afb6..231d03d 100644 --- a/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/yellow_cloth.json +++ b/src/generated/resources/data/createnuclear/recipe/shapeless/cloth/yellow_cloth.json @@ -2,9 +2,53 @@ "type": "minecraft:crafting_shapeless", "category": "building", "ingredients": [ - { - "tag": "createnuclear:cloth" - }, + [ + { + "item": "createnuclear:white_cloth" + }, + { + "item": "createnuclear:orange_cloth" + }, + { + "item": "createnuclear:magenta_cloth" + }, + { + "item": "createnuclear:light_blue_cloth" + }, + { + "item": "createnuclear:lime_cloth" + }, + { + "item": "createnuclear:pink_cloth" + }, + { + "item": "createnuclear:gray_cloth" + }, + { + "item": "createnuclear:light_gray_cloth" + }, + { + "item": "createnuclear:cyan_cloth" + }, + { + "item": "createnuclear:purple_cloth" + }, + { + "item": "createnuclear:blue_cloth" + }, + { + "item": "createnuclear:brown_cloth" + }, + { + "item": "createnuclear:green_cloth" + }, + { + "item": "createnuclear:red_cloth" + }, + { + "item": "createnuclear:black_cloth" + } + ], { "item": "minecraft:yellow_dye" } diff --git a/src/generated/resources/data/createnuclear/recipe/smelting/lead_ingot_for_lead_ore.json b/src/generated/resources/data/createnuclear/recipe/smelting/lead_ingot_for_lead_ore.json index dd2a275..6f79145 100644 --- a/src/generated/resources/data/createnuclear/recipe/smelting/lead_ingot_for_lead_ore.json +++ b/src/generated/resources/data/createnuclear/recipe/smelting/lead_ingot_for_lead_ore.json @@ -4,7 +4,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "tag": "createnuclear:lead_ores" + "tag": "c:ores/lead" }, "result": { "count": 1, diff --git a/src/generated/resources/data/createnuclear/recipe/smelting/nitrogen_concentrate_for_nitrogen_concentrate.json b/src/generated/resources/data/createnuclear/recipe/smelting/nitrogen_concentrate_for_nitrogen_concentrate.json new file mode 100644 index 0000000..7af575d --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smelting/nitrogen_concentrate_for_nitrogen_concentrate.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:smelting", + "category": "misc", + "cookingtime": 200, + "experience": 0.1, + "ingredient": { + "item": "createnuclear:nitrate" + }, + "result": { + "count": 1, + "id": "createnuclear:nitrogen_concentrate" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smelting/raw_uranium_for_uranium_ore.json b/src/generated/resources/data/createnuclear/recipe/smelting/raw_uranium_for_uranium_ore.json index 1e30bfc..45500cc 100644 --- a/src/generated/resources/data/createnuclear/recipe/smelting/raw_uranium_for_uranium_ore.json +++ b/src/generated/resources/data/createnuclear/recipe/smelting/raw_uranium_for_uranium_ore.json @@ -4,7 +4,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "tag": "createnuclear:uranium_ores" + "tag": "c:ores/uranium" }, "result": { "count": 1, diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_black.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_black.json new file mode 100644 index 0000000..17219d3 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_black.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:black_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_blue.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_blue.json new file mode 100644 index 0000000..9dc4004 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_blue.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:blue_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_brown.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_brown.json new file mode 100644 index 0000000..0d3717f --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_brown.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:brown_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_cyan.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_cyan.json new file mode 100644 index 0000000..4514859 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_cyan.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:cyan_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_gray.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_gray.json new file mode 100644 index 0000000..7402b5b --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_gray.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:gray_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_green.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_green.json new file mode 100644 index 0000000..db19a39 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_green.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:green_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_light_blue.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_light_blue.json new file mode 100644 index 0000000..e8fa30d --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_light_blue.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:light_blue_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_light_gray.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_light_gray.json new file mode 100644 index 0000000..fa1d460 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_light_gray.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:light_gray_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_lime.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_lime.json new file mode 100644 index 0000000..22b715f --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_lime.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:lime_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_magenta.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_magenta.json new file mode 100644 index 0000000..2416b0b --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_magenta.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:magenta_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_orange.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_orange.json new file mode 100644 index 0000000..63ff345 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_orange.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:orange_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_pink.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_pink.json new file mode 100644 index 0000000..ce0078d --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_pink.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:pink_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_purple.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_purple.json new file mode 100644 index 0000000..e93bac9 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_purple.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:purple_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_red.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_red.json new file mode 100644 index 0000000..48ec534 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_red.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:red_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_white.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_white.json new file mode 100644 index 0000000..a5661cc --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_white.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:white_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_yellow.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_yellow.json new file mode 100644 index 0000000..cf8b076 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_boots_yellow.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:yellow_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_boots" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_boots" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_black.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_black.json new file mode 100644 index 0000000..648d532 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_black.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:black_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_blue.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_blue.json new file mode 100644 index 0000000..78d552e --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_blue.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:blue_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_brown.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_brown.json new file mode 100644 index 0000000..015d096 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_brown.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:brown_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_cyan.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_cyan.json new file mode 100644 index 0000000..0b4587d --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_cyan.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:cyan_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_gray.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_gray.json new file mode 100644 index 0000000..e684c30 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_gray.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:gray_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_green.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_green.json new file mode 100644 index 0000000..e36b491 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_green.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:green_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_light_blue.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_light_blue.json new file mode 100644 index 0000000..e808653 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_light_blue.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:light_blue_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_light_gray.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_light_gray.json new file mode 100644 index 0000000..70f413f --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_light_gray.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:light_gray_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_lime.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_lime.json new file mode 100644 index 0000000..5a7046a --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_lime.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:lime_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_magenta.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_magenta.json new file mode 100644 index 0000000..89cf00c --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_magenta.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:magenta_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_orange.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_orange.json new file mode 100644 index 0000000..e76de38 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_orange.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:orange_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_pink.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_pink.json new file mode 100644 index 0000000..7be9a72 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_pink.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:pink_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_purple.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_purple.json new file mode 100644 index 0000000..5aa8140 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_purple.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:purple_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_red.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_red.json new file mode 100644 index 0000000..c224572 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_red.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:red_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_white.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_white.json new file mode 100644 index 0000000..b7c48ef --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_white.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:white_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_yellow.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_yellow.json new file mode 100644 index 0000000..0d317eb --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_chestplate_yellow.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:yellow_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_chestplate" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_chestplate" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_black.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_black.json new file mode 100644 index 0000000..28156b4 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_black.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:black_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_blue.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_blue.json new file mode 100644 index 0000000..3c9e281 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_blue.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:blue_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_brown.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_brown.json new file mode 100644 index 0000000..c412172 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_brown.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:brown_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_cyan.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_cyan.json new file mode 100644 index 0000000..2d4f0c8 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_cyan.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:cyan_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_gray.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_gray.json new file mode 100644 index 0000000..264ecf6 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_gray.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:gray_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_green.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_green.json new file mode 100644 index 0000000..4a57b98 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_green.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:green_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_light_blue.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_light_blue.json new file mode 100644 index 0000000..1d45dc9 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_light_blue.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:light_blue_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_light_gray.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_light_gray.json new file mode 100644 index 0000000..b1b9ed7 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_light_gray.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:light_gray_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_lime.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_lime.json new file mode 100644 index 0000000..394a25b --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_lime.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:lime_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_magenta.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_magenta.json new file mode 100644 index 0000000..7efe0d5 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_magenta.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:magenta_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_orange.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_orange.json new file mode 100644 index 0000000..0973c63 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_orange.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:orange_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_pink.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_pink.json new file mode 100644 index 0000000..abe2735 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_pink.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:pink_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_purple.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_purple.json new file mode 100644 index 0000000..7e8b843 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_purple.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:purple_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_red.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_red.json new file mode 100644 index 0000000..06077f7 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_red.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:red_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_white.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_white.json new file mode 100644 index 0000000..66b6aa3 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_white.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:white_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_yellow.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_yellow.json new file mode 100644 index 0000000..b706c3f --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_helmet_yellow.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:yellow_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_helmet" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_helmet" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_black.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_black.json new file mode 100644 index 0000000..0627736 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_black.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:black_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_blue.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_blue.json new file mode 100644 index 0000000..6a40168 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_blue.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:blue_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_brown.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_brown.json new file mode 100644 index 0000000..995899d --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_brown.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:brown_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_cyan.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_cyan.json new file mode 100644 index 0000000..5e62e49 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_cyan.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:cyan_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_gray.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_gray.json new file mode 100644 index 0000000..0ec323e --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_gray.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:gray_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_green.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_green.json new file mode 100644 index 0000000..9cad802 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_green.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:green_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_light_blue.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_light_blue.json new file mode 100644 index 0000000..555c194 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_light_blue.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:light_blue_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_light_gray.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_light_gray.json new file mode 100644 index 0000000..9355348 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_light_gray.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:light_gray_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_lime.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_lime.json new file mode 100644 index 0000000..ddcfc20 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_lime.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:lime_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_magenta.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_magenta.json new file mode 100644 index 0000000..c2ce95c --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_magenta.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:magenta_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_orange.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_orange.json new file mode 100644 index 0000000..0416007 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_orange.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:orange_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_pink.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_pink.json new file mode 100644 index 0000000..c71d8c9 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_pink.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:pink_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_purple.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_purple.json new file mode 100644 index 0000000..82d6907 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_purple.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:purple_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_red.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_red.json new file mode 100644 index 0000000..64cc226 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_red.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:red_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_white.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_white.json new file mode 100644 index 0000000..e2ca838 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_white.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:white_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_yellow.json b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_yellow.json new file mode 100644 index 0000000..6faf71c --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/smithing/default_anti_radiation_leggings_yellow.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:smithing_transform", + "addition": { + "item": "createnuclear:yellow_cloth" + }, + "base": { + "item": "createnuclear:default_anti_radiation_leggings" + }, + "result": { + "count": 1, + "id": "createnuclear:default_anti_radiation_leggings" + }, + "template": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/recipe/snow_powder/cooled_nitrogen_concentrate.json b/src/generated/resources/data/createnuclear/recipe/snow_powder/cooled_nitrogen_concentrate.json new file mode 100644 index 0000000..c5cbc83 --- /dev/null +++ b/src/generated/resources/data/createnuclear/recipe/snow_powder/cooled_nitrogen_concentrate.json @@ -0,0 +1,13 @@ +{ + "type": "createnuclear:snow_powder", + "ingredients": [ + { + "item": "createnuclear:nitrogen_concentrate" + } + ], + "results": [ + { + "id": "createnuclear:cooled_nitrogen_concentrate" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipe/splashing/crushed_raw_lead.json b/src/generated/resources/data/createnuclear/recipe/splashing/crushed_raw_lead.json similarity index 100% rename from src/generated/resources/data/create/recipe/splashing/crushed_raw_lead.json rename to src/generated/resources/data/createnuclear/recipe/splashing/crushed_raw_lead.json diff --git a/src/generated/resources/data/createnuclear/tags/block/fan_processing_catalysts/snow_powder.json b/src/generated/resources/data/createnuclear/tags/block/fan_processing_catalysts/snow_powder.json new file mode 100644 index 0000000..38b8ecd --- /dev/null +++ b/src/generated/resources/data/createnuclear/tags/block/fan_processing_catalysts/snow_powder.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:powder_snow" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/block/lead_ores.json b/src/generated/resources/data/createnuclear/tags/block/lead_ores.json deleted file mode 100644 index e456059..0000000 --- a/src/generated/resources/data/createnuclear/tags/block/lead_ores.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "values": [ - "createnuclear:deepslate_lead_ore", - "createnuclear:lead_ore" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/block/uranium_ores.json b/src/generated/resources/data/createnuclear/tags/block/uranium_ores.json deleted file mode 100644 index 548841c..0000000 --- a/src/generated/resources/data/createnuclear/tags/block/uranium_ores.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "values": [ - "createnuclear:deepslate_uranium_ore", - "createnuclear:uranium_ore" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/entity_type/irradiated_immune.json b/src/generated/resources/data/createnuclear/tags/entity_type/irradiated_immune.json index c12810e..e21140d 100644 --- a/src/generated/resources/data/createnuclear/tags/entity_type/irradiated_immune.json +++ b/src/generated/resources/data/createnuclear/tags/entity_type/irradiated_immune.json @@ -2,6 +2,7 @@ "values": [ "createnuclear:irradiated_cat", "createnuclear:irradiated_chicken", - "createnuclear:irradiated_wolf" + "createnuclear:irradiated_wolf", + "createnuclear:irradiated_cow" ] } \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/fluid/nitrogen.json b/src/generated/resources/data/createnuclear/tags/fluid/nitrogen.json new file mode 100644 index 0000000..027a7f7 --- /dev/null +++ b/src/generated/resources/data/createnuclear/tags/fluid/nitrogen.json @@ -0,0 +1,6 @@ +{ + "values": [ + "createnuclear:flowing_nitrogen", + "createnuclear:nitrogen" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/fluid/thorium.json b/src/generated/resources/data/createnuclear/tags/fluid/thorium.json new file mode 100644 index 0000000..b1583ad --- /dev/null +++ b/src/generated/resources/data/createnuclear/tags/fluid/thorium.json @@ -0,0 +1,6 @@ +{ + "values": [ + "createnuclear:flowing_thorium", + "createnuclear:thorium" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/fluid/uranium.json b/src/generated/resources/data/createnuclear/tags/fluid/uranium.json index f72d209..bcad219 100644 --- a/src/generated/resources/data/createnuclear/tags/fluid/uranium.json +++ b/src/generated/resources/data/createnuclear/tags/fluid/uranium.json @@ -1,3 +1,6 @@ { - "values": [] + "values": [ + "createnuclear:flowing_uranium", + "createnuclear:uranium" + ] } \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/all_anti_radiation_armors.json b/src/generated/resources/data/createnuclear/tags/item/all_anti_radiation_armors.json deleted file mode 100644 index 4151900..0000000 --- a/src/generated/resources/data/createnuclear/tags/item/all_anti_radiation_armors.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "values": [ - "createnuclear:white_anti_radiation_helmet", - "createnuclear:orange_anti_radiation_helmet", - "createnuclear:magenta_anti_radiation_helmet", - "createnuclear:light_blue_anti_radiation_helmet", - "createnuclear:yellow_anti_radiation_helmet", - "createnuclear:lime_anti_radiation_helmet", - "createnuclear:pink_anti_radiation_helmet", - "createnuclear:gray_anti_radiation_helmet", - "createnuclear:light_gray_anti_radiation_helmet", - "createnuclear:cyan_anti_radiation_helmet", - "createnuclear:purple_anti_radiation_helmet", - "createnuclear:blue_anti_radiation_helmet", - "createnuclear:brown_anti_radiation_helmet", - "createnuclear:green_anti_radiation_helmet", - "createnuclear:red_anti_radiation_helmet", - "createnuclear:black_anti_radiation_helmet", - "createnuclear:white_anti_radiation_chestplate", - "createnuclear:orange_anti_radiation_chestplate", - "createnuclear:magenta_anti_radiation_chestplate", - "createnuclear:light_blue_anti_radiation_chestplate", - "createnuclear:yellow_anti_radiation_chestplate", - "createnuclear:lime_anti_radiation_chestplate", - "createnuclear:pink_anti_radiation_chestplate", - "createnuclear:gray_anti_radiation_chestplate", - "createnuclear:light_gray_anti_radiation_chestplate", - "createnuclear:cyan_anti_radiation_chestplate", - "createnuclear:purple_anti_radiation_chestplate", - "createnuclear:blue_anti_radiation_chestplate", - "createnuclear:brown_anti_radiation_chestplate", - "createnuclear:green_anti_radiation_chestplate", - "createnuclear:red_anti_radiation_chestplate", - "createnuclear:black_anti_radiation_chestplate", - "createnuclear:white_anti_radiation_leggings", - "createnuclear:orange_anti_radiation_leggings", - "createnuclear:magenta_anti_radiation_leggings", - "createnuclear:light_blue_anti_radiation_leggings", - "createnuclear:yellow_anti_radiation_leggings", - "createnuclear:lime_anti_radiation_leggings", - "createnuclear:pink_anti_radiation_leggings", - "createnuclear:gray_anti_radiation_leggings", - "createnuclear:light_gray_anti_radiation_leggings", - "createnuclear:cyan_anti_radiation_leggings", - "createnuclear:purple_anti_radiation_leggings", - "createnuclear:blue_anti_radiation_leggings", - "createnuclear:brown_anti_radiation_leggings", - "createnuclear:green_anti_radiation_leggings", - "createnuclear:red_anti_radiation_leggings", - "createnuclear:black_anti_radiation_leggings", - "createnuclear:anti_radiation_boots" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_armor.json b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_armor.json index ae448c5..0fdc0c1 100644 --- a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_armor.json +++ b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_armor.json @@ -1,8 +1,8 @@ { "values": [ - "createnuclear:white_anti_radiation_helmet", - "createnuclear:white_anti_radiation_chestplate", - "createnuclear:white_anti_radiation_leggings", - "createnuclear:anti_radiation_boots" + "createnuclear:default_anti_radiation_helmet", + "createnuclear:default_anti_radiation_chestplate", + "createnuclear:default_anti_radiation_leggings", + "createnuclear:default_anti_radiation_boots" ] } \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_boots_dye.json b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_boots_dye.json deleted file mode 100644 index 3e6a775..0000000 --- a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_boots_dye.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "createnuclear:anti_radiation_boots" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_chestplate_dye.json b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_chestplate_dye.json deleted file mode 100644 index a1ac43a..0000000 --- a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_chestplate_dye.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "values": [ - "createnuclear:orange_anti_radiation_chestplate", - "createnuclear:magenta_anti_radiation_chestplate", - "createnuclear:light_blue_anti_radiation_chestplate", - "createnuclear:yellow_anti_radiation_chestplate", - "createnuclear:lime_anti_radiation_chestplate", - "createnuclear:pink_anti_radiation_chestplate", - "createnuclear:gray_anti_radiation_chestplate", - "createnuclear:light_gray_anti_radiation_chestplate", - "createnuclear:cyan_anti_radiation_chestplate", - "createnuclear:purple_anti_radiation_chestplate", - "createnuclear:blue_anti_radiation_chestplate", - "createnuclear:brown_anti_radiation_chestplate", - "createnuclear:green_anti_radiation_chestplate", - "createnuclear:red_anti_radiation_chestplate", - "createnuclear:black_anti_radiation_chestplate" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_chestplate_full_dye.json b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_chestplate_full_dye.json deleted file mode 100644 index 8b659b8..0000000 --- a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_chestplate_full_dye.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "values": [ - "createnuclear:white_anti_radiation_chestplate", - "createnuclear:orange_anti_radiation_chestplate", - "createnuclear:magenta_anti_radiation_chestplate", - "createnuclear:light_blue_anti_radiation_chestplate", - "createnuclear:yellow_anti_radiation_chestplate", - "createnuclear:lime_anti_radiation_chestplate", - "createnuclear:pink_anti_radiation_chestplate", - "createnuclear:gray_anti_radiation_chestplate", - "createnuclear:light_gray_anti_radiation_chestplate", - "createnuclear:cyan_anti_radiation_chestplate", - "createnuclear:purple_anti_radiation_chestplate", - "createnuclear:blue_anti_radiation_chestplate", - "createnuclear:brown_anti_radiation_chestplate", - "createnuclear:green_anti_radiation_chestplate", - "createnuclear:red_anti_radiation_chestplate", - "createnuclear:black_anti_radiation_chestplate" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_helmet.json b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_helmet.json new file mode 100644 index 0000000..855fd1a --- /dev/null +++ b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_helmet.json @@ -0,0 +1,5 @@ +{ + "values": [ + "createnuclear:default_anti_radiation_helmet" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_helmet_dye.json b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_helmet_dye.json deleted file mode 100644 index 7e34cb0..0000000 --- a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_helmet_dye.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "values": [ - "createnuclear:orange_anti_radiation_helmet", - "createnuclear:magenta_anti_radiation_helmet", - "createnuclear:light_blue_anti_radiation_helmet", - "createnuclear:yellow_anti_radiation_helmet", - "createnuclear:lime_anti_radiation_helmet", - "createnuclear:pink_anti_radiation_helmet", - "createnuclear:gray_anti_radiation_helmet", - "createnuclear:light_gray_anti_radiation_helmet", - "createnuclear:cyan_anti_radiation_helmet", - "createnuclear:purple_anti_radiation_helmet", - "createnuclear:blue_anti_radiation_helmet", - "createnuclear:brown_anti_radiation_helmet", - "createnuclear:green_anti_radiation_helmet", - "createnuclear:red_anti_radiation_helmet", - "createnuclear:black_anti_radiation_helmet" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_helmet_full_dye.json b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_helmet_full_dye.json deleted file mode 100644 index 7d378f7..0000000 --- a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_helmet_full_dye.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "values": [ - "createnuclear:white_anti_radiation_helmet", - "createnuclear:orange_anti_radiation_helmet", - "createnuclear:magenta_anti_radiation_helmet", - "createnuclear:light_blue_anti_radiation_helmet", - "createnuclear:yellow_anti_radiation_helmet", - "createnuclear:lime_anti_radiation_helmet", - "createnuclear:pink_anti_radiation_helmet", - "createnuclear:gray_anti_radiation_helmet", - "createnuclear:light_gray_anti_radiation_helmet", - "createnuclear:cyan_anti_radiation_helmet", - "createnuclear:purple_anti_radiation_helmet", - "createnuclear:blue_anti_radiation_helmet", - "createnuclear:brown_anti_radiation_helmet", - "createnuclear:green_anti_radiation_helmet", - "createnuclear:red_anti_radiation_helmet", - "createnuclear:black_anti_radiation_helmet" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_leggings_dye.json b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_leggings_dye.json deleted file mode 100644 index 155da49..0000000 --- a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_leggings_dye.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "values": [ - "createnuclear:orange_anti_radiation_leggings", - "createnuclear:magenta_anti_radiation_leggings", - "createnuclear:light_blue_anti_radiation_leggings", - "createnuclear:yellow_anti_radiation_leggings", - "createnuclear:lime_anti_radiation_leggings", - "createnuclear:pink_anti_radiation_leggings", - "createnuclear:gray_anti_radiation_leggings", - "createnuclear:light_gray_anti_radiation_leggings", - "createnuclear:cyan_anti_radiation_leggings", - "createnuclear:purple_anti_radiation_leggings", - "createnuclear:blue_anti_radiation_leggings", - "createnuclear:brown_anti_radiation_leggings", - "createnuclear:green_anti_radiation_leggings", - "createnuclear:red_anti_radiation_leggings", - "createnuclear:black_anti_radiation_leggings" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_leggings_full_dye.json b/src/generated/resources/data/createnuclear/tags/item/anti_radiation_leggings_full_dye.json deleted file mode 100644 index ea23843..0000000 --- a/src/generated/resources/data/createnuclear/tags/item/anti_radiation_leggings_full_dye.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "values": [ - "createnuclear:white_anti_radiation_leggings", - "createnuclear:orange_anti_radiation_leggings", - "createnuclear:magenta_anti_radiation_leggings", - "createnuclear:light_blue_anti_radiation_leggings", - "createnuclear:yellow_anti_radiation_leggings", - "createnuclear:lime_anti_radiation_leggings", - "createnuclear:pink_anti_radiation_leggings", - "createnuclear:gray_anti_radiation_leggings", - "createnuclear:light_gray_anti_radiation_leggings", - "createnuclear:cyan_anti_radiation_leggings", - "createnuclear:purple_anti_radiation_leggings", - "createnuclear:blue_anti_radiation_leggings", - "createnuclear:brown_anti_radiation_leggings", - "createnuclear:green_anti_radiation_leggings", - "createnuclear:red_anti_radiation_leggings", - "createnuclear:black_anti_radiation_leggings" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/fuel.json b/src/generated/resources/data/createnuclear/tags/item/fuel.json index 951757d..9efea37 100644 --- a/src/generated/resources/data/createnuclear/tags/item/fuel.json +++ b/src/generated/resources/data/createnuclear/tags/item/fuel.json @@ -1,5 +1,6 @@ { "values": [ - "createnuclear:uranium_rod" + "createnuclear:uranium_rod", + "createnuclear:thorium_rod" ] } \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/lead_ores.json b/src/generated/resources/data/createnuclear/tags/item/lead_ores.json deleted file mode 100644 index e456059..0000000 --- a/src/generated/resources/data/createnuclear/tags/item/lead_ores.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "values": [ - "createnuclear:deepslate_lead_ore", - "createnuclear:lead_ore" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/thorium_ores.json b/src/generated/resources/data/createnuclear/tags/item/thorium_ores.json new file mode 100644 index 0000000..f72d209 --- /dev/null +++ b/src/generated/resources/data/createnuclear/tags/item/thorium_ores.json @@ -0,0 +1,3 @@ +{ + "values": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/tags/item/uranium_ores.json b/src/generated/resources/data/createnuclear/tags/item/uranium_ores.json deleted file mode 100644 index 548841c..0000000 --- a/src/generated/resources/data/createnuclear/tags/item/uranium_ores.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "values": [ - "createnuclear:deepslate_uranium_ore", - "createnuclear:uranium_ore" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/biome/irradiated_land.json b/src/generated/resources/data/createnuclear/worldgen/biome/irradiated_land.json new file mode 100644 index 0000000..98f445d --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/biome/irradiated_land.json @@ -0,0 +1,39 @@ +{ + "carvers": {}, + "downfall": 0.0, + "effects": { + "ambient_sound": "createnuclear:biomes/wasteland", + "fog_color": 4742718, + "foliage_color": 5660222, + "grass_color": 9211739, + "mood_sound": { + "block_search_extent": 8, + "offset": 2.0, + "sound": "minecraft:ambient.cave", + "tick_delay": 6000 + }, + "particle": { + "options": { + "type": "createnuclear:irradiated_particles" + }, + "probability": 0.025 + }, + "sky_color": 3293490, + "water_color": 3887411, + "water_fog_color": 658954 + }, + "features": [], + "has_precipitation": false, + "spawn_costs": {}, + "spawners": { + "ambient": [], + "axolotls": [], + "creature": [], + "misc": [], + "monster": [], + "underground_water_creature": [], + "water_ambient": [], + "water_creature": [] + }, + "temperature": 2.0 +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/configured_feature/lead_ore.json b/src/generated/resources/data/createnuclear/worldgen/configured_feature/lead_ore.json index 75f7246..1825d43 100644 --- a/src/generated/resources/data/createnuclear/worldgen/configured_feature/lead_ore.json +++ b/src/generated/resources/data/createnuclear/worldgen/configured_feature/lead_ore.json @@ -2,7 +2,7 @@ "type": "minecraft:ore", "config": { "discard_chance_on_air_exposure": 0.0, - "size": 7, + "size": 12, "targets": [ { "state": { diff --git a/src/generated/resources/data/createnuclear/worldgen/configured_feature/nitrate_ore.json b/src/generated/resources/data/createnuclear/worldgen/configured_feature/nitrate_ore.json new file mode 100644 index 0000000..2287b3d --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/configured_feature/nitrate_ore.json @@ -0,0 +1,27 @@ +{ + "type": "minecraft:ore", + "config": { + "discard_chance_on_air_exposure": 0.0, + "size": 10, + "targets": [ + { + "state": { + "Name": "createnuclear:nitrate_ore" + }, + "target": { + "predicate_type": "minecraft:tag_match", + "tag": "minecraft:stone_ore_replaceables" + } + }, + { + "state": { + "Name": "createnuclear:deepslate_nitrate_ore" + }, + "target": { + "predicate_type": "minecraft:tag_match", + "tag": "minecraft:deepslate_ore_replaceables" + } + } + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/configured_feature/thorium_ore.json b/src/generated/resources/data/createnuclear/worldgen/configured_feature/thorium_ore.json new file mode 100644 index 0000000..f0e17e2 --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/configured_feature/thorium_ore.json @@ -0,0 +1,27 @@ +{ + "type": "minecraft:ore", + "config": { + "discard_chance_on_air_exposure": 0.0, + "size": 12, + "targets": [ + { + "state": { + "Name": "createnuclear:thorium_ore" + }, + "target": { + "predicate_type": "minecraft:tag_match", + "tag": "minecraft:stone_ore_replaceables" + } + }, + { + "state": { + "Name": "createnuclear:deepslate_thorium_ore" + }, + "target": { + "predicate_type": "minecraft:tag_match", + "tag": "minecraft:deepslate_ore_replaceables" + } + } + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/erosion.json b/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/erosion.json new file mode 100644 index 0000000..feb1cdb --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/erosion.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:add", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 1.0, + "from_y": 0, + "to_value": -1.0, + "to_y": 90 + }, + "argument2": { + "type": "minecraft:old_blended_noise", + "smear_scale_multiplier": 8.0, + "xz_factor": 80.0, + "xz_scale": 0.25, + "y_factor": 160.0, + "y_scale": 0.375 + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/final_density.json b/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/final_density.json new file mode 100644 index 0000000..feb1cdb --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/final_density.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:add", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 1.0, + "from_y": 0, + "to_value": -1.0, + "to_y": 90 + }, + "argument2": { + "type": "minecraft:old_blended_noise", + "smear_scale_multiplier": 8.0, + "xz_factor": 80.0, + "xz_scale": 0.25, + "y_factor": 160.0, + "y_scale": 0.375 + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/noise/irradiated/erosion.json b/src/generated/resources/data/createnuclear/worldgen/noise/irradiated/erosion.json new file mode 100644 index 0000000..5cb7823 --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/noise/irradiated/erosion.json @@ -0,0 +1,10 @@ +{ + "amplitudes": [ + 1.0, + 1.0, + 0.0, + 1.0, + 1.0 + ], + "firstOctave": -9 +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/noise_settings/irradiated_noise.json b/src/generated/resources/data/createnuclear/worldgen/noise_settings/irradiated_noise.json new file mode 100644 index 0000000..b59dbcf --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/noise_settings/irradiated_noise.json @@ -0,0 +1,327 @@ +{ + "aquifers_enabled": false, + "default_block": { + "Name": "createnuclear:steel_block" + }, + "default_fluid": { + "Name": "minecraft:air" + }, + "disable_mob_generation": false, + "legacy_random_source": false, + "noise": { + "height": 256, + "min_y": -32, + "size_horizontal": 1, + "size_vertical": 2 + }, + "noise_router": { + "barrier": 1.0, + "continents": "minecraft:overworld/continents", + "depth": "minecraft:overworld/depth", + "erosion": "createnuclear:irradiated/erosion", + "final_density": { + "type": "minecraft:blend_density", + "argument": "createnuclear:irradiated/final_density" + }, + "fluid_level_floodedness": 0.0, + "fluid_level_spread": 0.0, + "initial_density_without_jaggedness": { + "type": "minecraft:add", + "argument1": 0.1171875, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 0.0, + "from_y": -30, + "to_value": 1.0, + "to_y": -40 + }, + "argument2": { + "type": "minecraft:add", + "argument1": -0.1171875, + "argument2": { + "type": "minecraft:add", + "argument1": -0.078125, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 1.0, + "from_y": 240, + "to_value": 0.0, + "to_y": 256 + }, + "argument2": { + "type": "minecraft:add", + "argument1": 0.078125, + "argument2": { + "type": "minecraft:clamp", + "input": { + "type": "minecraft:add", + "argument1": -0.703125, + "argument2": { + "type": "minecraft:mul", + "argument1": 4.0, + "argument2": { + "type": "minecraft:quarter_negative", + "argument": { + "type": "minecraft:mul", + "argument1": "minecraft:overworld/depth", + "argument2": { + "type": "minecraft:cache_2d", + "argument": "minecraft:overworld/factor" + } + } + } + } + }, + "max": 64.0, + "min": -30.0 + } + } + } + } + } + } + }, + "lava": 0.0, + "ridges": "minecraft:overworld/ridges", + "temperature": { + "type": "minecraft:shifted_noise", + "noise": "minecraft:temperature", + "shift_x": "minecraft:shift_x", + "shift_y": 0.0, + "shift_z": "minecraft:shift_z", + "xz_scale": 0.25, + "y_scale": 0.0 + }, + "vegetation": { + "type": "minecraft:shifted_noise", + "noise": "minecraft:vegetation", + "shift_x": "minecraft:shift_x", + "shift_y": 0.0, + "shift_z": "minecraft:shift_z", + "xz_scale": 0.0, + "y_scale": 0.0 + }, + "vein_gap": 0.0, + "vein_ridged": 0.0, + "vein_toggle": 0.0 + }, + "ore_veins_enabled": false, + "sea_level": 32, + "spawn_target": [ + { + "continentalness": [ + -0.11, + 1.0 + ], + "depth": 0.0, + "erosion": [ + -1.0, + 1.0 + ], + "humidity": [ + -1.0, + 1.0 + ], + "offset": 0.0, + "temperature": [ + -1.0, + 1.0 + ], + "weirdness": [ + -1.0, + -0.16 + ] + }, + { + "continentalness": [ + -0.11, + 1.0 + ], + "depth": 0.0, + "erosion": [ + -1.0, + 1.0 + ], + "humidity": [ + -1.0, + 1.0 + ], + "offset": 0.0, + "temperature": [ + -1.0, + 1.0 + ], + "weirdness": [ + 0.16, + 1.0 + ] + } + ], + "surface_rule": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "createnuclear:irradiated_land" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.0465, + "min_threshold": 0.035, + "noise": "createnuclear:irradiated/erosion" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:lead_ore" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.0545, + "min_threshold": 0.039, + "noise": "createnuclear:irradiated/erosion" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:lead_block" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.069, + "min_threshold": 0.0545, + "noise": "createnuclear:irradiated/erosion" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:raw_lead_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:vertical_gradient", + "false_at_and_above": { + "above_bottom": 5 + }, + "random_name": "minecraft:bedrock_floor", + "true_at_and_below": { + "above_bottom": 0 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:bedrock" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:above_preliminary_surface" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "createnuclear:irradiated_land" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:raw_lead_block" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "createnuclear:irradiated_land" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:raw_lead_block" + } + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:vertical_gradient", + "false_at_and_above": { + "absolute": 4 + }, + "random_name": "minecraft:enriched", + "true_at_and_below": { + "absolute": -4 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:enriched_soul_soil" + } + } + } + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/placed_feature/lead_ore.json b/src/generated/resources/data/createnuclear/worldgen/placed_feature/lead_ore.json index e9eff26..0cc2bfa 100644 --- a/src/generated/resources/data/createnuclear/worldgen/placed_feature/lead_ore.json +++ b/src/generated/resources/data/createnuclear/worldgen/placed_feature/lead_ore.json @@ -3,7 +3,7 @@ "placement": [ { "type": "minecraft:count", - "count": 6 + "count": 10 }, { "type": "minecraft:in_square" @@ -13,15 +13,15 @@ "height": { "type": "minecraft:trapezoid", "max_inclusive": { - "absolute": 64 + "absolute": 60 }, "min_inclusive": { - "absolute": -64 + "absolute": -16 } } }, { - "type": "create:config_filter" + "type": "createnuclear:config_filter" } ] } \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/placed_feature/nitrate_ore.json b/src/generated/resources/data/createnuclear/worldgen/placed_feature/nitrate_ore.json new file mode 100644 index 0000000..cdfa1f6 --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/placed_feature/nitrate_ore.json @@ -0,0 +1,27 @@ +{ + "feature": "createnuclear:nitrate_ore", + "placement": [ + { + "type": "minecraft:count", + "count": 6 + }, + { + "type": "minecraft:in_square" + }, + { + "type": "minecraft:height_range", + "height": { + "type": "minecraft:trapezoid", + "max_inclusive": { + "absolute": 64 + }, + "min_inclusive": { + "absolute": -63 + } + } + }, + { + "type": "createnuclear:config_filter" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/placed_feature/striated_ores_overworld.json b/src/generated/resources/data/createnuclear/worldgen/placed_feature/striated_ores_overworld.json index d5ec73f..87db06f 100644 --- a/src/generated/resources/data/createnuclear/worldgen/placed_feature/striated_ores_overworld.json +++ b/src/generated/resources/data/createnuclear/worldgen/placed_feature/striated_ores_overworld.json @@ -3,7 +3,7 @@ "placement": [ { "type": "minecraft:rarity_filter", - "chance": 18 + "chance": 64 }, { "type": "minecraft:in_square" @@ -13,15 +13,15 @@ "height": { "type": "minecraft:uniform", "max_inclusive": { - "absolute": 70 + "absolute": 16 }, "min_inclusive": { - "absolute": -30 + "absolute": -63 } } }, { - "type": "create:config_filter" + "type": "createnuclear:config_filter" } ] } \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/placed_feature/thorium_ore.json b/src/generated/resources/data/createnuclear/worldgen/placed_feature/thorium_ore.json new file mode 100644 index 0000000..3a1cfe2 --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/placed_feature/thorium_ore.json @@ -0,0 +1,27 @@ +{ + "feature": "createnuclear:thorium_ore", + "placement": [ + { + "type": "minecraft:count", + "count": 6 + }, + { + "type": "minecraft:in_square" + }, + { + "type": "minecraft:height_range", + "height": { + "type": "minecraft:trapezoid", + "max_inclusive": { + "absolute": 55 + }, + "min_inclusive": { + "absolute": -16 + } + } + }, + { + "type": "createnuclear:config_filter" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/placed_feature/uranium_ore.json b/src/generated/resources/data/createnuclear/worldgen/placed_feature/uranium_ore.json index 5613d15..8487204 100644 --- a/src/generated/resources/data/createnuclear/worldgen/placed_feature/uranium_ore.json +++ b/src/generated/resources/data/createnuclear/worldgen/placed_feature/uranium_ore.json @@ -3,7 +3,7 @@ "placement": [ { "type": "minecraft:count", - "count": 6 + "count": 4 }, { "type": "minecraft:in_square" @@ -13,15 +13,15 @@ "height": { "type": "minecraft:trapezoid", "max_inclusive": { - "absolute": 64 + "absolute": 16 }, "min_inclusive": { - "absolute": -64 + "absolute": -63 } } }, { - "type": "create:config_filter" + "type": "createnuclear:config_filter" } ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/campfires.json b/src/generated/resources/data/minecraft/tags/block/campfires.json index 85982ef..a51c2ef 100644 --- a/src/generated/resources/data/minecraft/tags/block/campfires.json +++ b/src/generated/resources/data/minecraft/tags/block/campfires.json @@ -1,6 +1,5 @@ { "values": [ - "createnuclear:enriching_campfire", "createnuclear:enriching_campfire" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json index f2a19ca..7f60e9a 100644 --- a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json @@ -4,17 +4,25 @@ "createnuclear:reactor_core", "createnuclear:reactor_frame", "createnuclear:reactor_cooler", - "createnuclear:reactor_input", + "createnuclear:reactor_rod_input", + "createnuclear:reactor_fluid_input", "createnuclear:reactor_output", "createnuclear:reactor_controller", + "createnuclear:reactor_alarm", "createnuclear:enriching_campfire", + "createnuclear:deepslate_uranium_ore", "createnuclear:deepslate_lead_ore", + "createnuclear:deepslate_thorium_ore", + "createnuclear:uranium_ore", "createnuclear:lead_ore", + "createnuclear:thorium_ore", + "createnuclear:nitrate_ore", + "createnuclear:deepslate_nitrate_ore", "createnuclear:raw_uranium_block", "createnuclear:raw_lead_block", + "createnuclear:raw_thorium_block", "createnuclear:lead_block", - "createnuclear:deepslate_uranium_ore", - "createnuclear:uranium_ore", + "createnuclear:thorium_block", "createnuclear:steel_block", "createnuclear:autunite", "createnuclear:cut_autunite", diff --git a/src/generated/resources/data/minecraft/tags/block/needs_diamond_tool.json b/src/generated/resources/data/minecraft/tags/block/needs_diamond_tool.json index e661e22..188e478 100644 --- a/src/generated/resources/data/minecraft/tags/block/needs_diamond_tool.json +++ b/src/generated/resources/data/minecraft/tags/block/needs_diamond_tool.json @@ -4,12 +4,16 @@ "createnuclear:reactor_core", "createnuclear:reactor_frame", "createnuclear:reactor_cooler", - "createnuclear:reactor_input", + "createnuclear:reactor_rod_input", + "createnuclear:reactor_fluid_input", "createnuclear:reactor_output", "createnuclear:reactor_controller", - "createnuclear:raw_uranium_block", "createnuclear:enriched_soul_soil", "createnuclear:deepslate_uranium_ore", - "createnuclear:uranium_ore" + "createnuclear:deepslate_thorium_ore", + "createnuclear:uranium_ore", + "createnuclear:thorium_ore", + "createnuclear:raw_uranium_block", + "createnuclear:raw_thorium_block" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json b/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json index 52471c4..c393b20 100644 --- a/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json +++ b/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json @@ -1,8 +1,12 @@ { "values": [ + "createnuclear:deepslate_uranium_ore", "createnuclear:deepslate_lead_ore", + "createnuclear:deepslate_thorium_ore", + "createnuclear:uranium_ore", "createnuclear:lead_ore", - "createnuclear:deepslate_uranium_ore", - "createnuclear:uranium_ore" + "createnuclear:thorium_ore", + "createnuclear:nitrate_ore", + "createnuclear:deepslate_nitrate_ore" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/damage_type/no_knockback.json b/src/generated/resources/data/minecraft/tags/damage_type/no_knockback.json new file mode 100644 index 0000000..b2aff4f --- /dev/null +++ b/src/generated/resources/data/minecraft/tags/damage_type/no_knockback.json @@ -0,0 +1,6 @@ +{ + "values": [ + "createnuclear:radiation", + "createnuclear:fan_radiation" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/fluid/water.json b/src/generated/resources/data/minecraft/tags/fluid/water.json new file mode 100644 index 0000000..64bc4a8 --- /dev/null +++ b/src/generated/resources/data/minecraft/tags/fluid/water.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#createnuclear:nitrogen" + ] +} \ No newline at end of file diff --git a/src/main/java/lib/multiblock/SimpleMultiBlockAislePatternBuilder.java b/src/main/java/lib/multiblock/SimpleMultiBlockAislePatternBuilder.java index 77d9321..f5d5658 100644 --- a/src/main/java/lib/multiblock/SimpleMultiBlockAislePatternBuilder.java +++ b/src/main/java/lib/multiblock/SimpleMultiBlockAislePatternBuilder.java @@ -79,7 +79,7 @@ public T build(IPatternBuilder builder){ data.forEach((k,v)-> list.addAll(v)); return builder.make(list, lookup, blockProvider); } - + public BlockPos getDistanceController(char character) { var data = Util.parseBlockPattern(pattern, lookup.keySet()); var coreList = data.get(character); diff --git a/src/main/java/lib/multiblock/SimpleMultiBlockPattern.java b/src/main/java/lib/multiblock/SimpleMultiBlockPattern.java index d67ad5c..e737186 100644 --- a/src/main/java/lib/multiblock/SimpleMultiBlockPattern.java +++ b/src/main/java/lib/multiblock/SimpleMultiBlockPattern.java @@ -18,20 +18,19 @@ import java.util.function.Predicate; import java.util.function.Supplier; -public final class SimpleMultiBlockPattern implements IMultiBlockPattern { - private final List multiBlockOffsetPosList; - private final Map> predicateHashMap; - private final Map> blockProvider; +public record SimpleMultiBlockPattern(List multiBlockOffsetPosList, + Map> predicateHashMap, + Map> blockProvider) implements IMultiBlockPattern { - public SimpleMultiBlockPattern(List multiBlockOffsetPosList, Map> predicateMap, Map> blockSuppliers) { + public SimpleMultiBlockPattern(List multiBlockOffsetPosList, Map> predicateHashMap, Map> blockProvider) { this.multiBlockOffsetPosList = List.copyOf(multiBlockOffsetPosList); - this.predicateHashMap = Map.copyOf(predicateMap); - this.blockProvider = Map.copyOf(blockSuppliers); + this.predicateHashMap = Map.copyOf(predicateHashMap); + this.blockProvider = Map.copyOf(blockProvider); } public boolean matches(Level level, BlockPos blockPos, Rotation rotation) { for (MultiBlockOffsetPos multiBlockOffsetPos : multiBlockOffsetPosList) { - char character = multiBlockOffsetPos.caracter(); + char character = multiBlockOffsetPos.character(); Predicate predicate = predicateHashMap.get(character); BlockInWorld block = new BlockInWorld(level, blockPos.offset(multiBlockOffsetPos.pos().rotate(rotation)), false); @@ -43,7 +42,7 @@ public boolean matches(Level level, BlockPos blockPos, Rotation rotation) { public MultiblockMatchResult matchesWithResult(Level level, BlockPos blockPos, Rotation rotation) { List result = new ArrayList<>(); for (MultiBlockOffsetPos multiBlockOffsetPos : multiBlockOffsetPosList) { - char character = multiBlockOffsetPos.caracter(); + char character = multiBlockOffsetPos.character(); Predicate predicate = predicateHashMap.get(character); BlockInWorld block = new BlockInWorld(level, blockPos.offset(multiBlockOffsetPos.pos().rotate(rotation)), false); if (predicate == null || !predicate.test(block)) return null; @@ -58,22 +57,14 @@ public void construct(Level level, BlockPos blockPos, BiPredicate stateSupplier = blockProvider.get(character); if (stateSupplier != null) { var pos = blockPos.offset(multiBlockOffsetPos.pos().rotate(Rotation.NONE)); var state = stateSupplier.get(); - if (stateBiPredicate.test(character, state)) level.getServer().tell(new TickTask(3, () -> level.setBlock(pos, state, Block.UPDATE_ALL))); + if (stateBiPredicate.test(character, state)) + level.getServer().tell(new TickTask(3, () -> level.setBlock(pos, state, Block.UPDATE_ALL))); } } } - - @Override - public boolean matches(java.util.logging.Level level, BlockPos pos, Rotation rotation) { - return false; - } - - public List test() { - return this.multiBlockOffsetPosList; - } } diff --git a/src/main/java/lib/multiblock/SimpleMultiBlockPatternBuilder.java b/src/main/java/lib/multiblock/SimpleMultiBlockPatternBuilder.java deleted file mode 100644 index e7a56b7..0000000 --- a/src/main/java/lib/multiblock/SimpleMultiBlockPatternBuilder.java +++ /dev/null @@ -1,68 +0,0 @@ -package lib.multiblock; - -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import lib.multiblock.impl.IMultiBlockPatternBuilder; -import lib.multiblock.impl.IMultiBlockPatternBuilder; -import lib.multiblock.impl.IPatternBuilder; -import lib.multiblock.misc.MultiBlockOffsetPos; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.pattern.BlockInWorld; -import lib.multiblock.impl.IMultiBlockPattern; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.function.Predicate; -import java.util.function.Supplier; - -public final class SimpleMultiBlockPatternBuilder implements IMultiBlockPatternBuilder { - private static final Joiner COMA_SEPARATOR = Joiner.on(','); - public static SimpleMultiBlockPatternBuilder start() { - return new SimpleMultiBlockPatternBuilder(); - } - - private final Map> multiBlockOffsetPosList = Maps.newHashMap(); - private final Map> predicateHashMap = Maps.newHashMap(); - private final Map> blockProvider = Maps.newHashMap(); - - private SimpleMultiBlockPatternBuilder() {} - - private void ensureProperlyBuilt(List list) { - HashSet characters = new HashSet<>(); - list.forEach(multiBlockOffsetPos -> { - if (!predicateHashMap.containsKey(multiBlockOffsetPos.caracter())) - characters.add(multiBlockOffsetPos.caracter()); - }); - if (!characters.isEmpty()) - throw new IllegalStateException("Missing the following: \"%s\" for MultiBlock Pattern as they have not been defined".formatted(COMA_SEPARATOR.join(characters))); - } - - public SimpleMultiBlockPatternBuilder add(char character, BlockPos relativePos) { - multiBlockOffsetPosList.computeIfAbsent(character, ArrayList::new).add(new MultiBlockOffsetPos(character, relativePos)); - return this; - } - - public SimpleMultiBlockPatternBuilder where(char character, Predicate worldPredicate) { - if (!predicateHashMap.containsKey(character)) predicateHashMap.put(character, worldPredicate); - return this; - } - - public SimpleMultiBlockPatternBuilder block(char pSymbol, Supplier blockStateSupplier) { - blockProvider.put(pSymbol, blockStateSupplier); - return this; - } - - - public T build(IPatternBuilder builder) { - var coreList = multiBlockOffsetPosList.get('*'); - if (coreList == null || coreList.size() != 1) - throw new IllegalArgumentException("Failed to build pattern due to having more or less than one \"*\" defined! Have: %s Expected: 1".formatted(coreList != null ? coreList.size() : 0)); - List list = Lists.newArrayList(); - multiBlockOffsetPosList.forEach((k, v) -> list.addAll(v)); - return builder.make(list, predicateHashMap, blockProvider); - } -} diff --git a/src/main/java/lib/multiblock/impl/IBetterPattern.java b/src/main/java/lib/multiblock/impl/IBetterPattern.java deleted file mode 100644 index f992135..0000000 --- a/src/main/java/lib/multiblock/impl/IBetterPattern.java +++ /dev/null @@ -1,31 +0,0 @@ -package lib.multiblock.impl; - -import lib.multiblock.misc.MultiblockMatchResult; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.state.BlockState; - -import java.util.function.BiPredicate; - -public class IBetterPattern implements IMultiBlockPattern { - @Override - public boolean matches(Level level, BlockPos pos, Rotation rotation) { - return false; - } - - @Override - public MultiblockMatchResult matchesWithResult(Level level, BlockPos pos, Rotation rotation) { - return null; - } - - @Override - public void construct(Level level, BlockPos pos, BiPredicate blockStateBiPredicate) { - - } - - @Override - public boolean matches(java.util.logging.Level level, BlockPos pos, Rotation rotation) { - return false; - } -} diff --git a/src/main/java/lib/multiblock/impl/IMultiBlockPattern.java b/src/main/java/lib/multiblock/impl/IMultiBlockPattern.java index 7453566..a33dee0 100644 --- a/src/main/java/lib/multiblock/impl/IMultiBlockPattern.java +++ b/src/main/java/lib/multiblock/impl/IMultiBlockPattern.java @@ -34,7 +34,4 @@ default MultiblockMatchResult matchesWithResult(Level level, BlockPos pos) { default void contruct(Level level, BlockPos pos) { construct(level, pos, (a,b) -> true); } - - - boolean matches(java.util.logging.Level level, BlockPos pos, Rotation rotation); -} +} \ No newline at end of file diff --git a/src/main/java/lib/multiblock/impl/IMultiBlockPatternBuilder.java b/src/main/java/lib/multiblock/impl/IMultiBlockPatternBuilder.java index 17c87dd..b5c34c5 100644 --- a/src/main/java/lib/multiblock/impl/IMultiBlockPatternBuilder.java +++ b/src/main/java/lib/multiblock/impl/IMultiBlockPatternBuilder.java @@ -2,6 +2,7 @@ import lib.multiblock.SimpleMultiBlockPattern; +@SuppressWarnings("unchecked") public interface IMultiBlockPatternBuilder { < T extends IMultiBlockPattern> T build(IPatternBuilder builder); diff --git a/src/main/java/lib/multiblock/impl/IPatternBuilder.java b/src/main/java/lib/multiblock/impl/IPatternBuilder.java index 53c1f00..ca33951 100644 --- a/src/main/java/lib/multiblock/impl/IPatternBuilder.java +++ b/src/main/java/lib/multiblock/impl/IPatternBuilder.java @@ -11,4 +11,4 @@ public interface IPatternBuilder { T make(List multiBlockOffsetPos, Map> predicateMap, Map> blockSuppliers); -} +} \ No newline at end of file diff --git a/src/main/java/lib/multiblock/manager/MultiBlockCache.java b/src/main/java/lib/multiblock/manager/MultiBlockCache.java deleted file mode 100644 index 5a2c97f..0000000 --- a/src/main/java/lib/multiblock/manager/MultiBlockCache.java +++ /dev/null @@ -1,25 +0,0 @@ -package lib.multiblock.manager; - -import lib.multiblock.impl.IMultiBlockPattern; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.Rotation; - -import java.util.logging.Level; - -public class MultiBlockCache { - private T cachedResult; - public MultiBlockCache(){} - - public void updateStructure(T blockPattern) { - this.cachedResult = blockPattern; - } - - public boolean isValid(Level level, BlockPos pos, Rotation rotation) { - return cachedResult != null && cachedResult.matches(level, pos, rotation); - } - - public boolean isCached() { - return cachedResult == null; - } -} diff --git a/src/main/java/lib/multiblock/manager/MultiBlockManager.java b/src/main/java/lib/multiblock/manager/MultiBlockManager.java deleted file mode 100644 index dd8dbf4..0000000 --- a/src/main/java/lib/multiblock/manager/MultiBlockManager.java +++ /dev/null @@ -1,27 +0,0 @@ -package lib.multiblock.manager; - -import lib.multiblock.impl.IMultiBlockPattern; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Rotation; - -import java.util.ArrayList; - -public class MultiBlockManager { - private final ArrayList> registeredMultiBlockPatterns = new ArrayList>(); - - public MultiBlockManager(){} - - public E register(String ID, T data, E blockPattern) { - registeredMultiBlockPatterns.add(new RegisteredMultiBlockPattern<>(ID, data, blockPattern)); - return blockPattern; - } - - public RegisteredMultiBlockPattern findStructure(Level level, BlockPos pos, Rotation rotation) { - for (RegisteredMultiBlockPattern registeredMultiBlockPattern : registeredMultiBlockPatterns) { - var result = registeredMultiBlockPattern.pattern().matches(level, pos, rotation); - if(result) return registeredMultiBlockPattern; - } - return null; - } -} diff --git a/src/main/java/lib/multiblock/manager/RegisteredMultiBlockPattern.java b/src/main/java/lib/multiblock/manager/RegisteredMultiBlockPattern.java deleted file mode 100644 index 264af6d..0000000 --- a/src/main/java/lib/multiblock/manager/RegisteredMultiBlockPattern.java +++ /dev/null @@ -1,6 +0,0 @@ -package lib.multiblock.manager; - -import lib.multiblock.impl.IMultiBlockPattern; - -public record RegisteredMultiBlockPattern (String ID, T data, IMultiBlockPattern pattern) { -} diff --git a/src/main/java/lib/multiblock/misc/MultiBlockOffsetPos.java b/src/main/java/lib/multiblock/misc/MultiBlockOffsetPos.java index a388a68..11801a7 100644 --- a/src/main/java/lib/multiblock/misc/MultiBlockOffsetPos.java +++ b/src/main/java/lib/multiblock/misc/MultiBlockOffsetPos.java @@ -2,5 +2,5 @@ import net.minecraft.core.BlockPos; -public record MultiBlockOffsetPos(char caracter, BlockPos pos) { +public record MultiBlockOffsetPos(char character, BlockPos pos) { } diff --git a/src/main/java/lib/multiblock/misc/Util.java b/src/main/java/lib/multiblock/misc/Util.java index 81eb1ef..184f034 100644 --- a/src/main/java/lib/multiblock/misc/Util.java +++ b/src/main/java/lib/multiblock/misc/Util.java @@ -20,14 +20,12 @@ public static Map> parseBlockPattern(List> blockOffsets = new HashMap<>(); - int starX = -1; - int starY = -1; - int starZ = -1; + int starX = -1, starY = -1, starZ = -1; for (int y = 0; y < aisles.size(); y++) { String[] aisle = aisles.get(y); - for (int x=0; x < aisle.length; x++) { + for (int x = 0; x < aisle.length; x++) { for (int z = 0; z < aisle[x].length(); z++) { if (aisle[x].charAt(z) == '*') { starX = x; diff --git a/src/main/java/net/nuclearteam/createnuclear/CNAttachmentTypes.java b/src/main/java/net/nuclearteam/createnuclear/CNAttachmentTypes.java new file mode 100644 index 0000000..f23287d --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/CNAttachmentTypes.java @@ -0,0 +1,25 @@ +package net.nuclearteam.createnuclear; + +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.attachment.AttachmentType; +import net.neoforged.neoforge.registries.DeferredRegister; +import net.neoforged.neoforge.registries.NeoForgeRegistries; +import net.nuclearteam.createnuclear.content.radiation.capability.RadiationCapability; + +import java.util.function.Supplier; + +public class CNAttachmentTypes { + public static final DeferredRegister> ATTACHMENT_TYPES = DeferredRegister.create(NeoForgeRegistries.Keys.ATTACHMENT_TYPES, CreateNuclear.MOD_ID); + + public static final Supplier> RADIATION = ATTACHMENT_TYPES.register("radiation", () -> AttachmentType + .builder(RadiationCapability::new) + .serialize(RadiationCapability.CODEC) + .sync(RadiationCapability.STREAM_CODEC) + .build() + ); + + public static void register(IEventBus modEventBus) { + ATTACHMENT_TYPES.register(modEventBus); + } + +} diff --git a/src/main/java/net/nuclearteam/createnuclear/CNAttributes.java b/src/main/java/net/nuclearteam/createnuclear/CNAttributes.java new file mode 100644 index 0000000..136a500 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/CNAttributes.java @@ -0,0 +1,19 @@ +package net.nuclearteam.createnuclear; + +import net.minecraft.core.registries.Registries; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.RangedAttribute; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredRegister; + +import net.neoforged.neoforge.registries.DeferredHolder; + +public class CNAttributes { + public static final DeferredRegister ATTRIBUTES = DeferredRegister.create(Registries.ATTRIBUTE, CreateNuclear.MOD_ID); + + public static final DeferredHolder IRRADIATED_RESISTANCE = ATTRIBUTES.register("generic.irradiated_resistance", () -> new RangedAttribute("attribute.name.createnuclear.generic.irradiated_resistance", 0, 0, 1).setSyncable(true)); + + public static void register(IEventBus eventBus) { + ATTRIBUTES.register(eventBus); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/CNBlockEntityTypes.java b/src/main/java/net/nuclearteam/createnuclear/CNBlockEntityTypes.java index f8a469c..6c65045 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNBlockEntityTypes.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNBlockEntityTypes.java @@ -4,10 +4,14 @@ import com.simibubi.create.content.kinetics.base.OrientedRotatingVisual; import com.tterrag.registrate.util.entry.BlockEntityEntry; import net.nuclearteam.createnuclear.content.enriching.campfire.EnrichingCampfireBlockEntity; +import net.nuclearteam.createnuclear.content.multiblock.alarm.ReactorAlarmEntity; import net.nuclearteam.createnuclear.content.multiblock.casing.ReactorCasingEntity; import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; import net.nuclearteam.createnuclear.content.multiblock.core.ReactorCoreEntity; -import net.nuclearteam.createnuclear.content.multiblock.input.ReactorInputEntity; +import net.nuclearteam.createnuclear.content.multiblock.frame.ReactorFrameEntity; +import net.nuclearteam.createnuclear.content.multiblock.frame.ReactorFrameRenderer; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.ReactorFluidInputEntity; +import net.nuclearteam.createnuclear.content.multiblock.input.item.ReactorRodInputEntity; import net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutputEntity; import net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutputRenderer; @@ -27,9 +31,20 @@ public class CNBlockEntityTypes { .validBlocks(CNBlocks.REACTOR_CORE) .register(); - public static final BlockEntityEntry REACTOR_INPUT = - CreateNuclear.REGISTRATE.blockEntity("reactor_input", ReactorInputEntity::new) - .validBlocks(CNBlocks.REACTOR_INPUT) + public static final BlockEntityEntry REACTOR_FRAME = + CreateNuclear.REGISTRATE.blockEntity("reactor_frame", ReactorFrameEntity::new) + .validBlocks(CNBlocks.REACTOR_FRAME) + .renderer(() -> ReactorFrameRenderer::new) + .register(); + + public static final BlockEntityEntry REACTOR_INPUT = + CreateNuclear.REGISTRATE.blockEntity("reactor_input", ReactorRodInputEntity::new) + .validBlocks(CNBlocks.REACTOR_ROD_INPUT) + .register(); + + public static final BlockEntityEntry REACTOR_FLUID_INPUT = + CreateNuclear.REGISTRATE.blockEntity("reactor_fluid_input", ReactorFluidInputEntity::new) + .validBlocks(CNBlocks.REACTOR_FLUID_INPUT) .register(); public static final BlockEntityEntry REACTOR_OUTPUT = @@ -44,5 +59,10 @@ public class CNBlockEntityTypes { .validBlocks(CNBlocks.REACTOR_CONTROLLER) .register(); + public static final BlockEntityEntry REACTOR_ALARM = + CreateNuclear.REGISTRATE.blockEntity("reactor_alarm", ReactorAlarmEntity::new) + .validBlocks(CNBlocks.REACTOR_ALARM) + .register(); + public static void register() {} } diff --git a/src/main/java/net/nuclearteam/createnuclear/CNBlocks.java b/src/main/java/net/nuclearteam/createnuclear/CNBlocks.java index 4245ac6..950477c 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNBlocks.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNBlocks.java @@ -9,7 +9,6 @@ import com.tterrag.registrate.providers.RegistrateRecipeProvider; import com.tterrag.registrate.providers.loot.RegistrateBlockLootTables; import com.tterrag.registrate.util.entry.BlockEntry; -import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.Registries; @@ -31,27 +30,33 @@ import net.minecraft.world.level.material.MapColor; import net.minecraft.world.level.storage.loot.entries.LootItem; import net.minecraft.world.level.storage.loot.functions.ApplyBonusCount; +import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction; +import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; import net.neoforged.neoforge.client.model.generators.ConfiguredModel; import net.neoforged.neoforge.client.model.generators.ModelFile; import net.neoforged.neoforge.common.Tags; import net.nuclearteam.createnuclear.content.enriching.campfire.EnrichingCampfireBlock; import net.nuclearteam.createnuclear.content.enriching.fire.EnrichingFireBlock; +import net.nuclearteam.createnuclear.content.multiblock.alarm.ReactorAlarm; import net.nuclearteam.createnuclear.content.multiblock.casing.ReactorCasing; import net.nuclearteam.createnuclear.CNTags.CNBlockTags; -import net.nuclearteam.createnuclear.CNTags.CNItemTags; import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock; import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerGenerator; import net.nuclearteam.createnuclear.content.multiblock.core.ReactorCore; import net.nuclearteam.createnuclear.content.multiblock.frame.ReactorFrame; import net.nuclearteam.createnuclear.content.multiblock.frame.ReactorframeItem; -import net.nuclearteam.createnuclear.content.multiblock.input.ReactorInput; -import net.nuclearteam.createnuclear.content.multiblock.input.ReactorInputGenerator; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.ReactorFluidInput; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.ReactorFluidInputGenerator; +import net.nuclearteam.createnuclear.content.multiblock.input.item.ReactorRodInput; +import net.nuclearteam.createnuclear.content.multiblock.input.item.ReactorRodInputGenerator; import net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutput; import net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutputGenerator; -import net.nuclearteam.createnuclear.content.multiblock.reactorCooler.ReactorCooler; +import net.nuclearteam.createnuclear.content.multiblock.cooler.ReactorCooler; import net.nuclearteam.createnuclear.content.multiblock.reinforced.ReinforcedGlassBlock; import net.nuclearteam.createnuclear.content.uraniumOre.UraniumOreBlock; +import net.nuclearteam.createnuclear.content.uraniumOre.UraniumOreItem; +import static com.simibubi.create.api.behaviour.display.DisplaySource.displaySource; import static com.simibubi.create.foundation.data.CreateRegistrate.casingConnectivity; import static com.simibubi.create.foundation.data.ModelGen.customItemModel; import static com.simibubi.create.foundation.data.TagGen.axeOrPickaxe; @@ -63,444 +68,625 @@ public class CNBlocks { CreateNuclear.REGISTRATE.setCreativeTab(CNCreativeModeTabs.MAIN); } - public static final BlockEntry REACTOR_CASING = - CreateNuclear.REGISTRATE.block("reactor_casing", properties -> new ReactorCasing(properties, ReactorCasing.TypeBlock.CASING)) - .properties(p -> p.explosionResistance(3F) - .destroyTime(4F)) - .blockstate((c,p) -> - p.getVariantBuilder(c.getEntry()).forAllStates((state) -> ConfiguredModel.builder() - .modelFile(p.models().getExistingFile(p.modLoc("block/reactor/casing/block"))) - .build())) - .onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(CNSpriteShifts.REACTOR_CASING))) - .onRegister(casingConnectivity((block,cc) -> cc.makeCasing(block, CNSpriteShifts.REACTOR_CASING))) - .tag(BlockTags.NEEDS_DIAMOND_TOOL) - .simpleItem() - .transform(pickaxeOnly()) - .register(); - - public static final BlockEntry REACTOR_CORE = - CreateNuclear.REGISTRATE.block("reactor_core", ReactorCore::new) - .properties(p -> p.explosionResistance(6F)) - .properties(p -> p.destroyTime(4F)) - .tag(BlockTags.NEEDS_DIAMOND_TOOL) - .blockstate((c, p) -> - p.getVariantBuilder(c.getEntry()) - .forAllStates(state -> ConfiguredModel.builder() - .modelFile(p.models().getExistingFile(p.modLoc("block/reactor/core/block"))) - .uvLock(false) - .build() - ) + public static final BlockEntry REACTOR_CASING = CreateNuclear.REGISTRATE + .block("reactor_casing", properties -> new ReactorCasing(properties, ReactorCasing.TypeBlock.CASING)) + .properties(p -> p + .explosionResistance(3F) + .destroyTime(4F) + ) + .blockstate((c, p) -> p.getVariantBuilder(c.getEntry()).forAllStates((state) -> ConfiguredModel.builder() + .modelFile(p.models().getExistingFile(p.modLoc("block/reactor/casing/block"))) + .build())) + .onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(CNSpriteShifts.REACTOR_CASING))) + .onRegister(casingConnectivity((block, cc) -> cc.makeCasing(block, CNSpriteShifts.REACTOR_CASING))) + .tag(BlockTags.NEEDS_DIAMOND_TOOL) + .simpleItem() + .transform(pickaxeOnly()) + .transform(displaySource(CNDisplaySources.HEAT)) + .transform(displaySource(CNDisplaySources.LIQUID_LEVEL)) + .transform(displaySource(CNDisplaySources.FUEL)) + .transform(displaySource(CNDisplaySources.COOLER)) + .transform(displaySource(CNDisplaySources.REACTOR_SIZE)) + .transform(displaySource(CNDisplaySources.REACTOR_SUMMARY)) + .register(); + + public static final BlockEntry REACTOR_CORE = CreateNuclear.REGISTRATE + .block("reactor_core", ReactorCore::new) + .properties(p -> p.explosionResistance(6F)) + .properties(p -> p.destroyTime(4F)) + .tag(BlockTags.NEEDS_DIAMOND_TOOL) + .blockstate((c, p) -> p.getVariantBuilder(c.getEntry()) + .forAllStates(state -> ConfiguredModel.builder() + .modelFile(p.models().getExistingFile(p.modLoc("block/reactor/core/block"))) + .uvLock(false) + .build() ) - .transform(pickaxeOnly()) - .simpleItem() - .register(); - - public static final BlockEntry REACTOR_FRAME = - CreateNuclear.REGISTRATE.block("reactor_frame", ReactorFrame::new) - .initialProperties(SharedProperties::stone) - .properties(p -> p.explosionResistance(3F).destroyTime(2F)) - .addLayer(() -> RenderType::cutoutMipped) - .transform(pickaxeOnly()) - .tag(BlockTags.NEEDS_DIAMOND_TOOL) - .blockstate((c, p) -> - p.getVariantBuilder(c.getEntry()) - .forAllStatesExcept(state -> { - ReactorFrame.Part part = state.getValue(ReactorFrame.PART); - String baseFile = "block/reactor/frame/frame_"; - ModelFile start = p.models().getExistingFile(p.modLoc(baseFile + "top")); - ModelFile middle = p.models().getExistingFile(p.modLoc(baseFile + "middle")); - ModelFile bottom = p.models().getExistingFile(p.modLoc(baseFile + "bottom")); - ModelFile none = p.models().getExistingFile(p.modLoc(baseFile + "none")); - return ConfiguredModel.builder().modelFile(switch (part) { - case START -> start; - case MIDDLE -> middle; - case END -> bottom; - default -> none; - }) - .uvLock(false) - .build(); + ) + .transform(pickaxeOnly()) + .simpleItem() + .register(); + + public static final BlockEntry REACTOR_FRAME = CreateNuclear.REGISTRATE + .block("reactor_frame", ReactorFrame::new) + .initialProperties(SharedProperties::stone) + .properties(p -> p.explosionResistance(3F).destroyTime(2F).noOcclusion()) + .transform(pickaxeOnly()) + .tag(BlockTags.NEEDS_DIAMOND_TOOL) + .blockstate((c, p) -> p.getVariantBuilder(c.getEntry()) + .forAllStatesExcept(state -> { + ReactorFrame.Part part = state.getValue(ReactorFrame.PART); + String baseFile = "block/reactor/frame/frame_"; + ModelFile start = p.models().getExistingFile(p.modLoc(baseFile + "top")); + ModelFile middle = p.models().getExistingFile(p.modLoc(baseFile + "middle")); + ModelFile bottom = p.models().getExistingFile(p.modLoc(baseFile + "bottom")); + ModelFile none = p.models().getExistingFile(p.modLoc(baseFile + "none")); + return ConfiguredModel.builder().modelFile(switch (part) { + case START -> start; + case MIDDLE -> middle; + case END -> bottom; + default -> none; }) - ) - .item(ReactorframeItem::new) - .model(AssetLookup.customBlockItemModel("reactor", "frame", "item")) - .build() - .register(); - - public static final BlockEntry REACTOR_COOLER = - CreateNuclear.REGISTRATE.block("reactor_cooler", ReactorCooler::new) - .properties(p -> p.explosionResistance(3F) - .destroyTime(4F)) - .blockstate((c,p) -> - p.getVariantBuilder(c.getEntry()).forAllStates((state) -> ConfiguredModel.builder() - .modelFile(p.models().getExistingFile(p.modLoc("block/reactor/cooler/block"))) - .build())) - .tag(BlockTags.NEEDS_DIAMOND_TOOL) - .simpleItem() - .transform(pickaxeOnly()) - .register(); - - - public static final BlockEntry REACTOR_INPUT = - CreateNuclear.REGISTRATE.block("reactor_input", ReactorInput::new) - .initialProperties(SharedProperties::stone) - .properties(p -> p.explosionResistance(6F)) - .properties(p -> p.destroyTime(2F)) - .addLayer(() -> RenderType::cutoutMipped) - .transform(pickaxeOnly()) - .tag(BlockTags.NEEDS_DIAMOND_TOOL) - .blockstate(new ReactorInputGenerator()::generate) - .item() - .transform(customItemModel("reactor", "input", "item")) - .register(); - - public static final BlockEntry REACTOR_OUTPUT = - CreateNuclear.REGISTRATE.block("reactor_output", ReactorOutput::new) - .properties(p -> p.explosionResistance(6F).destroyTime(4F)) - .initialProperties(SharedProperties::stone) - .properties(p -> p.mapColor(MapColor.COLOR_PURPLE).forceSolidOn()) - .tag(AllTags.AllBlockTags.SAFE_NBT.tag, BlockTags.NEEDS_DIAMOND_TOOL) - .transform(pickaxeOnly()) - .blockstate(new ReactorOutputGenerator()::generate) - .onRegister(block -> BlockStressValues.CAPACITIES.register(block, () -> 10240.0)) - .item() - .transform(customItemModel("reactor", "output", "item")) - .register(); - - public static final BlockEntry REACTOR_CONTROLLER = - CreateNuclear.REGISTRATE.block("reactor_controller", ReactorControllerBlock::new) - .initialProperties(SharedProperties::stone) - .properties(p -> p.explosionResistance(6F)) - .properties(p -> p.destroyTime(4F)) - .transform(pickaxeOnly()) - .tag(BlockTags.NEEDS_DIAMOND_TOOL) - .blockstate(new ReactorControllerGenerator()::generate) - .item() - .transform(customItemModel("reactor", "controller", "item")) - .register(); + .uvLock(false) + .build(); + })) + .item(ReactorframeItem::new) + .model(AssetLookup.customBlockItemModel("reactor", "frame", "item")) + .build() + .register(); + + public static final BlockEntry REACTOR_COOLER = CreateNuclear.REGISTRATE + .block("reactor_cooler", ReactorCooler::new) + .properties(p -> p + .explosionResistance(3F) + .destroyTime(4F)) + .blockstate((c, p) -> p.getVariantBuilder(c.getEntry()).forAllStates((state) -> ConfiguredModel.builder() + .modelFile(p.models().getExistingFile(p.modLoc("block/reactor/cooler/block"))) + .build())) + .tag(BlockTags.NEEDS_DIAMOND_TOOL) + .simpleItem() + .transform(pickaxeOnly()) + .register(); + + public static final BlockEntry REACTOR_ROD_INPUT = CreateNuclear.REGISTRATE + .block("reactor_rod_input", ReactorRodInput::new) + .initialProperties(SharedProperties::stone) + .properties(p -> p + .explosionResistance(6F) + .destroyTime(2F) + ) + .transform(pickaxeOnly()) + .tag(BlockTags.NEEDS_DIAMOND_TOOL) + .blockstate(new ReactorRodInputGenerator()::generate) + .item() + .transform(customItemModel("reactor", "rod_input", "item")) + .register(); + + + public static final BlockEntry REACTOR_FLUID_INPUT = CreateNuclear.REGISTRATE + .block("reactor_fluid_input", ReactorFluidInput::new) + .initialProperties(SharedProperties::stone) + .properties(p -> p + .explosionResistance(6F) + .destroyTime(2F) + ) + .transform(pickaxeOnly()) + .tag(BlockTags.NEEDS_DIAMOND_TOOL) + .blockstate(new ReactorFluidInputGenerator()::generate) + .item() + .transform(customItemModel("reactor", "fluid_input", "item")) + .register(); + + public static final BlockEntry REACTOR_OUTPUT = CreateNuclear.REGISTRATE + .block("reactor_output", ReactorOutput::new) + .initialProperties(SharedProperties::stone) + .properties(p -> p + .explosionResistance(6F) + .destroyTime(4F) + .mapColor(MapColor.COLOR_PURPLE) + .forceSolidOn() + ) + .tag(AllTags.AllBlockTags.SAFE_NBT.tag, BlockTags.NEEDS_DIAMOND_TOOL) + .transform(pickaxeOnly()) + .blockstate(new ReactorOutputGenerator()::generate) + .onRegister(block -> BlockStressValues.CAPACITIES.register(block, () -> 64000.0)) + .item() + .transform(customItemModel("reactor", "output", "item")) + .register(); + + public static final BlockEntry REACTOR_CONTROLLER = CreateNuclear.REGISTRATE + .block("reactor_controller", ReactorControllerBlock::new) + .initialProperties(SharedProperties::stone) + .properties(p -> p + .explosionResistance(6F) + .destroyTime(4F) + ) + .transform(pickaxeOnly()) + .tag(BlockTags.NEEDS_DIAMOND_TOOL) + .blockstate(new ReactorControllerGenerator()::generate) + .transform(displaySource(CNDisplaySources.HEAT)) + .transform(displaySource(CNDisplaySources.LIQUID_LEVEL)) + .transform(displaySource(CNDisplaySources.FUEL)) + .transform(displaySource(CNDisplaySources.COOLER)) + .transform(displaySource(CNDisplaySources.REACTOR_SIZE)) + .transform(displaySource(CNDisplaySources.REACTOR_SUMMARY)) + .item() + .transform(customItemModel("reactor", "controller", "item")) + .register(); + + public static final BlockEntry REACTOR_ALARM = CreateNuclear.REGISTRATE + .block("reactor_alarm", ReactorAlarm::new) + .initialProperties(SharedProperties::stone) + .transform(pickaxeOnly()) + .item() + .build() + .register(); public static final BlockEntry REINFORCED_GLASS = CreateNuclear.REGISTRATE .block("reinforced_glass", ReinforcedGlassBlock::new) .initialProperties(() -> Blocks.GLASS) - .properties(p -> p.explosionResistance(7.0F).destroyTime(2F)) + .properties(p -> p + .explosionResistance(1200.0F) + .destroyTime(2F) + ) .onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(CNSpriteShifts.REACTOR_GLASS))) .onRegister(casingConnectivity((block,cc) -> cc.makeCasing(block, CNSpriteShifts.REACTOR_GLASS))) .loot(RegistrateBlockLootTables::dropWhenSilkTouch) - .tag(CNTags.forgeBlockTag("glass_blocks"), BlockTags.IMPERMEABLE) + .tag(Tags.Blocks.GLASS_BLOCKS, BlockTags.IMPERMEABLE) .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, c.get()) - .unlockedBy("has_reactor_casing", RegistrateRecipeProvider.has(CNBlocks.REACTOR_CASING.get())) - .define('G', CNTags.forgeItemTag("glass_blocks")) - .define('S', CNTags.forgeItemTag("ingots/lead")) - .pattern("SGS") - .pattern("GSG") - .pattern("SGS") - .showNotification(true) - .save(p, CreateNuclear.asResource("crafting/reactor/" + c.getName()))) + .unlockedBy("has_reactor_casing", RegistrateRecipeProvider.has(CNBlocks.REACTOR_CASING.get())) + .define('G', Tags.Items.GLASS_BLOCKS) + .define('S', CNTags.forgeItemTag("ingots/lead")) + .pattern("SGS") + .pattern("GSG") + .pattern("SGS") + .showNotification(true) + .save(p, CreateNuclear.asResource("crafting/reactor/" + c.getName())) + ) .blockstate((c, p) -> p.getVariantBuilder(c.getEntry()) - .forAllStates(state -> ConfiguredModel.builder().modelFile(p.models() - .withExistingParent("reinforced_glass",ResourceLocation.withDefaultNamespace("block/cube_all")) + .forAllStates(state -> ConfiguredModel.builder().modelFile( + p.models() + .withExistingParent("reinforced_glass", ResourceLocation.withDefaultNamespace("block/cube_all")) .texture("all", p.modLoc("block/reactor/reinforced/glass")) .texture("particle", p.modLoc("block/reactor/reinforced/glass")) + .renderType("translucent") ) .build()) ) - .addLayer(() -> RenderType::translucent) .item() - .tag(CNTags.forgeItemTag("glass_blocks")) + .tag(Tags.Items.GLASS_BLOCKS) .build() .register(); + public static final BlockEntry ENRICHING_FIRE = CreateNuclear.REGISTRATE + .block("enriching_fire", properties -> new EnrichingFireBlock(properties, 3.0f)) + .initialProperties(() -> Blocks.FIRE) + .properties(Properties::replaceable) + .properties(Properties::noCollission) + .properties(Properties::noOcclusion) + .properties(EnrichingFireBlock.getLight()) + .tag(CNBlockTags.FAN_PROCESSING_CATALYSTS_ENRICHED.tag) + .loot((lt, b) -> lt.add(b, BlockLootSubProvider.noDrop())) + .blockstate((c, p) -> { + String baseFolder = "block/enriching/fire/"; + ModelFile Floor0 = p.models().getExistingFile(p.modLoc(baseFolder + "floor0")); + ModelFile Floor1 = p.models().getExistingFile(p.modLoc(baseFolder + "floor1")); + ModelFile Side0 = p.models().getExistingFile(p.modLoc(baseFolder + "side0")); + ModelFile Side1 = p.models().getExistingFile(p.modLoc(baseFolder + "side1")); + ModelFile SideAlt0 = p.models().getExistingFile(p.modLoc(baseFolder + "side_alt0")); + ModelFile SideAlt1 = p.models().getExistingFile(p.modLoc(baseFolder + "side_alt1")); + + p.getMultipartBuilder(c.get()) + .part() + .modelFile(Floor0) + .nextModel() + .modelFile(Floor1) + .addModel() + .end() + .part() + .modelFile(Side0) + .nextModel() + .modelFile(Side1) + .nextModel() + .modelFile(SideAlt0) + .nextModel() + .modelFile(SideAlt1) + .addModel() + .end() + .part() + .modelFile(Side0).rotationY(90).nextModel() + .modelFile(Side1).rotationY(90).nextModel() + .modelFile(SideAlt0).rotationY(90).nextModel() + .modelFile(SideAlt1).rotationY(90) + .addModel() + .end() + .part() + .modelFile(Side0).rotationY(180).nextModel() + .modelFile(Side1).rotationY(180).nextModel() + .modelFile(SideAlt0).rotationY(180).nextModel() + .modelFile(SideAlt1).rotationY(180) + .addModel() + .end() + .part() + .modelFile(Side0).rotationY(270).nextModel() + .modelFile(Side1).rotationY(270).nextModel() + .modelFile(SideAlt0).rotationY(270).nextModel() + .modelFile(SideAlt1).rotationY(270) + .addModel() + .end(); + }) + .register(); + + public static final BlockEntry ENRICHING_CAMPFIRE = CreateNuclear.REGISTRATE + .block("enriching_campfire", properties -> new EnrichingCampfireBlock(properties, true, 5)) + .properties(p -> p.mapColor(MapColor.PODZOL) + .instrument(NoteBlockInstrument.BASS) + .strength(2.0F) + .sound(SoundType.WOOD) + .lightLevel(EnrichingCampfireBlock::getLight)) + .properties(Properties::noOcclusion) + .properties(Properties::ignitedByLava) + .transform(axeOrPickaxe()) + .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.MISC, c.get()) + .unlockedBy("has_enriched_soul_soil", RegistrateRecipeProvider.has(CNBlocks.ENRICHED_SOUL_SOIL.get())) + .define('E', CNBlocks.ENRICHED_SOUL_SOIL) + .define('L', ItemTags.LOGS) + .define('S', Tags.Items.RODS_WOODEN) + .pattern(" S ") + .pattern("SES") + .pattern("LLL") + .showNotification(true) + .save(p, CreateNuclear.asResource("crafting/" + c.getName()))) + .loot((lt, b) -> lt.add(b, lt.createSilkTouchDispatchTable(b, lt.applyExplosionDecay(b, LootItem.lootTableItem(CNBlocks.ENRICHED_SOUL_SOIL))))) + .blockstate((c, p) -> + p.getVariantBuilder(c.getEntry()).forAllStatesExcept(state -> { + Direction facing = state.getValue(BlockStateProperties.HORIZONTAL_FACING); + return ConfiguredModel.builder() + .modelFile(p.models().getExistingFile(p.modLoc("block/enriching/campfire/" + (state.getValue(EnrichingCampfireBlock.LIT) ? "block" : "block_off")))) + .uvLock(false) + .rotationY(switch (facing) { + case NORTH -> 180; + case WEST -> 90; + case EAST -> 270; + default -> 0; + }) + .build(); + }, BlockStateProperties.SIGNAL_FIRE, BlockStateProperties.WATERLOGGED)) + .item() + .model((c, p) -> + p.withExistingParent(c.getName(), ResourceLocation.withDefaultNamespace("item/generated")) + .texture("layer0", p.modLoc("item/enriched/campfire")) + ) + .build() + .tag(CNBlockTags.FAN_PROCESSING_CATALYSTS_ENRICHED.tag) + .register(); + + + public static final BlockEntry ENRICHED_SOUL_SOIL = CreateNuclear.REGISTRATE + .block("enriched_soul_soil", Block::new) + .initialProperties(() -> Blocks.SOUL_SOIL) + .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, c.get()) + .unlockedBy("has_nether_star", RegistrateRecipeProvider.has(Items.NETHER_STAR)) + .define('S', Blocks.SOUL_SOIL) + .define('O', Blocks.OBSIDIAN) + .define('N', Items.NETHER_STAR) + .pattern("SOS") + .pattern("ONO") + .pattern("SOS") + .showNotification(true) + .save(p, CreateNuclear.asResource("crafting/" + c.getName())) + ) + .simpleItem() + .tag(BlockTags.MINEABLE_WITH_SHOVEL) + .tag(CNBlockTags.ENRICHING_FIRE_BASE_BLOCKS.tag, BlockTags.NEEDS_DIAMOND_TOOL) + .register(); + public static final BlockEntry DEEPSLATE_URANIUM_ORE = CreateNuclear.REGISTRATE + .block("deepslate_uranium_ore", UraniumOreBlock::new) + .initialProperties(() -> Blocks.DIAMOND_ORE) + .properties(UraniumOreBlock.litBlockEmission()) + .transform(pickaxeOnly()) + .loot((lt, b) -> { + HolderLookup.RegistryLookup enchantmentRegistryLookup = lt.getRegistries().lookupOrThrow(Registries.ENCHANTMENT); + lt.add(b, + lt.createSilkTouchDispatchTable(b, + lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.RAW_URANIUM) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(3.0F, 4.0F))) + .apply(ApplyBonusCount.addUniformBonusCount(lt.getRegistries().holderOrThrow(Enchantments.FORTUNE), 1))))); + }) + .tag( + BlockTags.NEEDS_DIAMOND_TOOL, + BlockTags.NEEDS_IRON_TOOL, + Tags.Blocks.ORES, + Tags.Blocks.ORES_IN_GROUND_DEEPSLATE, + CNTags.forgeBlockTag("ores/uranium") + ) + .item((b, p) -> new UraniumOreItem(b, p, 3)) + .tag(Tags.Items.ORES, CNTags.forgeItemTag("ores/uranium")) + .build() + .register(); - public static final BlockEntry ENRICHING_FIRE = - CreateNuclear.REGISTRATE.block("enriching_fire", properties -> new EnrichingFireBlock(properties, 3.0f)) - .initialProperties(() -> Blocks.FIRE) - .properties(Properties::replaceable) - .properties(Properties::noCollission) - .properties(Properties::noOcclusion) - .properties(EnrichingFireBlock.getLight()) - .tag(CNBlockTags.FAN_PROCESSING_CATALYSTS_ENRICHED.tag) - .loot((lt, b) -> lt.add(b, BlockLootSubProvider.noDrop())) - .addLayer(() -> RenderType::cutout) - .blockstate((c, p) -> { - String baseFolder = "block/enriching/fire/"; - ModelFile Floor0 = p.models().getExistingFile(p.modLoc(baseFolder + "floor0")); - ModelFile Floor1 = p.models().getExistingFile(p.modLoc(baseFolder + "floor1")); - ModelFile Side0 = p.models().getExistingFile(p.modLoc(baseFolder + "side0")); - ModelFile Side1 = p.models().getExistingFile(p.modLoc(baseFolder + "side1")); - ModelFile SideAlt0 = p.models().getExistingFile(p.modLoc(baseFolder + "side_alt0")); - ModelFile SideAlt1 = p.models().getExistingFile(p.modLoc(baseFolder + "side_alt1")); - - p.getMultipartBuilder(c.get()) - .part() - .modelFile(Floor0) - .nextModel() - .modelFile(Floor1) - .addModel() - .end() - .part() - .modelFile(Side0) - .nextModel() - .modelFile(Side1) - .nextModel() - .modelFile(SideAlt0) - .nextModel() - .modelFile(SideAlt1) - .addModel() - .end() - .part() - .modelFile(Side0).rotationY(90).nextModel() - .modelFile(Side1).rotationY(90).nextModel() - .modelFile(SideAlt0).rotationY(90).nextModel() - .modelFile(SideAlt1).rotationY(90) - .addModel() - .end() - .part() - .modelFile(Side0).rotationY(180).nextModel() - .modelFile(Side1).rotationY(180).nextModel() - .modelFile(SideAlt0).rotationY(180).nextModel() - .modelFile(SideAlt1).rotationY(180) - .addModel() - .end() - .part() - .modelFile(Side0).rotationY(270).nextModel() - .modelFile(Side1).rotationY(270).nextModel() - .modelFile(SideAlt0).rotationY(270).nextModel() - .modelFile(SideAlt1).rotationY(270) - .addModel() - .end(); - }) - .register() - ; - - public static final BlockEntry ENRICHING_CAMPFIRE = - CreateNuclear.REGISTRATE.block("enriching_campfire", properties -> new EnrichingCampfireBlock(properties, true, 5)) - .properties(p -> p.mapColor(MapColor.PODZOL) - .instrument(NoteBlockInstrument.BASS) - .strength(2.0F) - .sound(SoundType.WOOD) - .lightLevel(EnrichingCampfireBlock::getLight)) - .properties(Properties::noOcclusion) - .properties(Properties::ignitedByLava) - .addLayer(() -> RenderType::cutoutMipped) - .transform(axeOrPickaxe()) - .tag(BlockTags.CAMPFIRES) - .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.MISC, c.get()) - .unlockedBy("has_enriched_soul_soil", RegistrateRecipeProvider.has(CNBlocks.ENRICHED_SOUL_SOIL.get())) - .define('E', CNBlocks.ENRICHED_SOUL_SOIL) - .define('L', ItemTags.LOGS) - .define('S', Tags.Items.RODS_WOODEN) - .pattern(" S ") - .pattern("SES") - .pattern("LLL") - .showNotification(true) - .save(p, CreateNuclear.asResource("crafting/" + c.getName()))) - .loot((lt, b) -> lt.add(b, + public static final BlockEntry DEEPSLATE_LEAD_ORE = CreateNuclear.REGISTRATE + .block("deepslate_lead_ore", Block::new) + .initialProperties(() -> Blocks.DIAMOND_ORE) + .simpleItem() + .transform(pickaxeOnly()) + .loot((lt, b) -> { + HolderLookup.RegistryLookup enchantmentRegistryLookup = lt.getRegistries().lookupOrThrow(Registries.ENCHANTMENT); + lt.add(b, lt.createSilkTouchDispatchTable(b, - lt.applyExplosionDecay(b, LootItem.lootTableItem(CNBlocks.ENRICHED_SOUL_SOIL))))) - .blockstate((c, p) -> - p.getVariantBuilder(c.getEntry()).forAllStatesExcept(state -> { - Direction facing = state.getValue(BlockStateProperties.HORIZONTAL_FACING); - return ConfiguredModel.builder() - .modelFile(p.models().getExistingFile(p.modLoc("block/enriching/campfire/" + (state.getValue(EnrichingCampfireBlock.LIT) ? "block" : "block_off")))) - .uvLock(false) - .rotationY(switch (facing) { - case NORTH -> 180; - case WEST -> 90; - case EAST -> 270; - default -> 0; - }) - .build(); - }, BlockStateProperties.SIGNAL_FIRE, BlockStateProperties.WATERLOGGED + lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.RAW_LEAD) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(2.0F, 4.0F))) + .apply(ApplyBonusCount.addUniformBonusCount(lt.getRegistries().holderOrThrow(Enchantments.FORTUNE), 4))))); + }) + .tag( + BlockTags.NEEDS_IRON_TOOL, + Tags.Blocks.ORES, + Tags.Blocks.ORES_IN_GROUND_DEEPSLATE, + CNTags.forgeBlockTag("ores/lead") + ) + .item() + .tag(Tags.Items.ORES, CNTags.forgeItemTag("ores/lead")) + .build() + .register(); + + public static final BlockEntry DEEPSLATE_THORIUM_ORE = CreateNuclear.REGISTRATE + .block("deepslate_thorium_ore", Block::new) + .initialProperties(() -> Blocks.DIAMOND_ORE) + .simpleItem() + .transform(pickaxeOnly()) + .loot((lt, b) -> lt.add(b, + lt.createSilkTouchDispatchTable(b, + lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.RAW_THORIUM) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(2.0F, 5.0F))) + .apply(ApplyBonusCount.addUniformBonusCount(lt.getRegistries().holderOrThrow(Enchantments.FORTUNE), 5)) ) ) - .item() - .model((c, p) -> - p.withExistingParent(c.getName(), ResourceLocation.withDefaultNamespace("item/generated")) - .texture("layer0", p.modLoc("item/enriched/campfire")) - ) - .build() - .tag(CNBlockTags.FAN_PROCESSING_CATALYSTS_ENRICHED.tag) - .register(); - - public static final BlockEntry DEEPSLATE_LEAD_ORE = - CreateNuclear.REGISTRATE.block("deepslate_lead_ore", Block::new) - .initialProperties(() -> Blocks.DIAMOND_ORE) - .simpleItem() - .transform(pickaxeOnly()) - .loot((lt, b) -> { - HolderLookup.RegistryLookup enchantmentRegistryLookup = lt.getRegistries().lookupOrThrow(Registries.ENCHANTMENT); - lt.add(b, - lt.createSilkTouchDispatchTable(b, - lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.RAW_LEAD) - .apply(ApplyBonusCount.addOreBonusCount(enchantmentRegistryLookup.getOrThrow(Enchantments.FORTUNE)))))); - }) - .tag(BlockTags.NEEDS_IRON_TOOL, - CNTags.forgeBlockTag("ores"), - CNTags.forgeBlockTag("ores_in_ground/deepslate"), - CNTags.forgeBlockTag("ores/lead"), - CNBlockTags.LEAD_ORES.tag - ) - .item() - .tag(CNItemTags.LEAD_ORES.tag, - CNTags.forgeItemTag("ores/lead")) - .build() - .register(); - - public static final BlockEntry LEAD_ORE = - CreateNuclear.REGISTRATE.block("lead_ore", Block::new) - .initialProperties(SharedProperties::stone) - .simpleItem() - .transform(pickaxeOnly()) - .loot((lt, b) -> { - HolderLookup.RegistryLookup enchantmentRegistryLookup = lt.getRegistries().lookupOrThrow(Registries.ENCHANTMENT); - lt.add(b, - lt.createSilkTouchDispatchTable(b, - lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.RAW_LEAD) - .apply(ApplyBonusCount.addOreBonusCount(enchantmentRegistryLookup.getOrThrow(Enchantments.FORTUNE)))))); - }) - .tag(BlockTags.NEEDS_IRON_TOOL, - CNTags.forgeBlockTag("ores"), - CNTags.forgeBlockTag("ores_in_ground/stone"), - CNTags.forgeBlockTag("ores/lead"), - CNBlockTags.LEAD_ORES.tag - ) - .item() - .tag(CNItemTags.LEAD_ORES.tag, - CNTags.forgeItemTag("ores/lead")) - .build() - .register(); - - public static final BlockEntry RAW_URANIUM_BLOCK = - CreateNuclear.REGISTRATE.block("raw_uranium_block", Block::new) - .initialProperties(SharedProperties::stone) - .transform(pickaxeOnly()) - .tag(BlockTags.NEEDS_DIAMOND_TOOL, - CNTags.forgeBlockTag("storage_blocks/raw_uranium")) - .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, c.get()) - .unlockedBy("has_raw_materials_uranium", RegistrateRecipeProvider.has(CNTags.forgeItemTag("raw_materials/uranium"))) - .define('R', CNTags.forgeItemTag("raw_materials/uranium")) - .pattern("RRR") - .pattern("RRR") - .pattern("RRR") - .save(p, CreateNuclear.asResource("crafting/" + c.getName()))) - .item() - .tag(CNTags.forgeItemTag("storage_blocks/raw_uranium")) - .build() - .register(); - - public static final BlockEntry RAW_LEAD_BLOCK = - CreateNuclear.REGISTRATE.block("raw_lead_block", Block::new) - .initialProperties(SharedProperties::stone) - .transform(pickaxeOnly()) - .tag(CNTags.forgeBlockTag("storage_blocks/raw_lead")) - .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, c.get()) - .unlockedBy("has_raw_materials_lead", RegistrateRecipeProvider.has(CNTags.forgeItemTag("raw_materials/lead"))) - .define('R', CNTags.forgeItemTag("raw_materials/lead")) - .pattern("RRR") - .pattern("RRR") - .pattern("RRR") - .save(p, CreateNuclear.asResource("crafting/" + c.getName()))) - .item() - .tag(CNTags.forgeItemTag("storage_blocks/raw_lead")) - .build() - .register(); - - public static final BlockEntry LEAD_BLOCK = - CreateNuclear.REGISTRATE.block("lead_block", Block::new) - .initialProperties(SharedProperties::stone) - .transform(pickaxeOnly()) - .tag(CNTags.forgeBlockTag("storage_blocks/lead")) - .item() - .tag(CNTags.forgeItemTag("storage_blocks/lead")) - .build() - .register(); - - public static final BlockEntry ENRICHED_SOUL_SOIL = - CreateNuclear.REGISTRATE.block("enriched_soul_soil", Block::new) - .initialProperties(() -> Blocks.SOUL_SOIL) - .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, c.get()) - .unlockedBy("has_nether_star", RegistrateRecipeProvider.has(Items.NETHER_STAR)) - .define('S', Blocks.SOUL_SOIL) - .define('O', Blocks.OBSIDIAN) - .define('N', Items.NETHER_STAR) - .pattern("SOS") - .pattern("ONO") - .pattern("SOS") - .showNotification(true) - .save(p, CreateNuclear.asResource("crafting/" + c.getName())) - ) - .simpleItem() - .tag(BlockTags.MINEABLE_WITH_SHOVEL) - .tag(CNBlockTags.ENRICHING_FIRE_BASE_BLOCKS.tag, BlockTags.NEEDS_DIAMOND_TOOL) - .register(); - - public static final BlockEntry DEEPSLATE_URANIUM_ORE = - CreateNuclear.REGISTRATE.block("deepslate_uranium_ore", UraniumOreBlock::new) - .initialProperties(() -> Blocks.DIAMOND_ORE) - .properties(UraniumOreBlock.litBlockEmission()) - .transform(pickaxeOnly()) - .loot((lt, b) -> { - HolderLookup.RegistryLookup enchantmentRegistryLookup = lt.getRegistries().lookupOrThrow(Registries.ENCHANTMENT); - lt.add(b, - lt.createSilkTouchDispatchTable(b, - lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.RAW_URANIUM) - .apply(ApplyBonusCount.addOreBonusCount(enchantmentRegistryLookup.getOrThrow(Enchantments.FORTUNE)))))); - }) - .tag(BlockTags.NEEDS_DIAMOND_TOOL, - BlockTags.NEEDS_IRON_TOOL, - CNTags.forgeBlockTag("ores"), - CNTags.forgeBlockTag("ores_in_ground/deepslate"), - CNTags.forgeBlockTag("ores/uranium"), - CNBlockTags.URANIUM_ORES.tag - ) - .item() - .tag(CNItemTags.URANIUM_ORES.tag, - CNTags.forgeItemTag("ores/uranium")) - .build() - .register(); - - public static final BlockEntry URANIUM_ORE = - CreateNuclear.REGISTRATE.block("uranium_ore", UraniumOreBlock::new) - .initialProperties(SharedProperties::stone) - .properties(UraniumOreBlock.litBlockEmission()) - .simpleItem() - .transform(pickaxeOnly()) - .loot((lt, b) -> { - HolderLookup.RegistryLookup enchantmentRegistryLookup = lt.getRegistries().lookupOrThrow(Registries.ENCHANTMENT); - lt.add(b, - lt.createSilkTouchDispatchTable(b, - lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.RAW_URANIUM) - .apply(ApplyBonusCount.addOreBonusCount(enchantmentRegistryLookup.getOrThrow(Enchantments.FORTUNE)))))); - }) - .tag(BlockTags.NEEDS_DIAMOND_TOOL, - BlockTags.NEEDS_IRON_TOOL, - CNTags.forgeBlockTag("ores"), - CNTags.forgeBlockTag("ores_in_ground/stone"), - CNTags.forgeBlockTag("ores/uranium"), - CNBlockTags.URANIUM_ORES.tag - ) - .item() - .tag(CNItemTags.URANIUM_ORES.tag, - CNTags.forgeItemTag("ores/uranium")) - .build() - .register(); - - public static final BlockEntry STEEL_BLOCK = - CreateNuclear.REGISTRATE.block("steel_block", Block::new) - .initialProperties(SharedProperties::stone) - .transform(pickaxeOnly()) - .tag(CNTags.forgeBlockTag("storage_blocks/steel")) - .item() - .tag(CNTags.forgeItemTag("storage_blocks/steel")) - .build() - .register(); - - /*public static final BlockEntry TEST_EVENT_TRIGGER_BLOCK = CreateNuclear.REGISTRATE.block("test_event_trigger_block", EventTriggerBlock::new) - .defaultBlockstate() - .defaultLang() - .simpleItem() - .register();*/ + )) + .tag( + BlockTags.NEEDS_DIAMOND_TOOL, + BlockTags.NEEDS_IRON_TOOL, + Tags.Blocks.ORES, + Tags.Blocks.ORES_IN_GROUND_DEEPSLATE, + CNTags.forgeBlockTag("ores/thorium") + ) + .item() + .tag(Tags.Items.ORES, CNTags.forgeItemTag("ores/thorium")) + .build() + .register(); + + public static final BlockEntry URANIUM_ORE = CreateNuclear.REGISTRATE + .block("uranium_ore", UraniumOreBlock::new) + .initialProperties(SharedProperties::stone) + .properties(UraniumOreBlock.litBlockEmission()) + .simpleItem() + .transform(pickaxeOnly()) + .loot((lt, b) -> { + HolderLookup.RegistryLookup enchantmentRegistryLookup = lt.getRegistries().lookupOrThrow(Registries.ENCHANTMENT); + lt.add(b, + lt.createSilkTouchDispatchTable(b, + lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.RAW_URANIUM) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(3.0F, 4.0F))) + .apply(ApplyBonusCount.addUniformBonusCount(enchantmentRegistryLookup.getOrThrow(Enchantments.FORTUNE)))))); + }) + .tag( + BlockTags.NEEDS_DIAMOND_TOOL, + BlockTags.NEEDS_IRON_TOOL, + Tags.Blocks.ORES, + Tags.Blocks.ORES_IN_GROUND_STONE, + CNTags.forgeBlockTag("ores/uranium") + ) + .item((b, p) -> new UraniumOreItem(b, p, 3)) + .tag(Tags.Items.ORES, CNTags.forgeItemTag("ores/uranium")) + .build() + .register(); + + public static final BlockEntry LEAD_ORE = CreateNuclear.REGISTRATE + .block("lead_ore", Block::new) + .initialProperties(SharedProperties::stone) + .simpleItem() + .transform(pickaxeOnly()) + .loot((lt, b) -> { + HolderLookup.RegistryLookup enchantmentRegistryLookup = lt.getRegistries().lookupOrThrow(Registries.ENCHANTMENT); + lt.add(b, + lt.createSilkTouchDispatchTable(b, + lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.RAW_LEAD) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(2.0F, 4.0F))) + .apply(ApplyBonusCount.addUniformBonusCount(enchantmentRegistryLookup.getOrThrow(Enchantments.FORTUNE), 4))))); + }) + .tag( + BlockTags.NEEDS_IRON_TOOL, + Tags.Blocks.ORES, + Tags.Blocks.ORES_IN_GROUND_STONE, + CNTags.forgeBlockTag("ores/lead") + ) + .item() + .tag(Tags.Items.ORES, CNTags.forgeItemTag("ores/lead")) + .build() + .register(); + + + public static final BlockEntry THORIUM_ORE = CreateNuclear.REGISTRATE + .block("thorium_ore", Block::new) + .initialProperties(SharedProperties::stone) + .simpleItem() + .transform(pickaxeOnly()) + .loot((lt, b) -> lt.add(b, + lt.createSilkTouchDispatchTable(b, + lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.RAW_THORIUM) + .apply(SetItemCountFunction.setCount(UniformGenerator.between(2.0F, 5.0F))) + .apply(ApplyBonusCount.addUniformBonusCount(lt.getRegistries().holderOrThrow(Enchantments.FORTUNE), 5)))))) + .tag( + BlockTags.NEEDS_DIAMOND_TOOL, + BlockTags.NEEDS_IRON_TOOL, + Tags.Blocks.ORES, + Tags.Blocks.ORES_IN_GROUND_STONE, + CNTags.forgeBlockTag("ores/thorium") + ) + .item() + .tag(Tags.Items.ORES, CNTags.forgeItemTag("ores/thorium")) + .build() + .register(); + + public static final BlockEntry NITRATE_ORE = CreateNuclear.REGISTRATE + .block("nitrate_ore", Block::new) + .initialProperties(SharedProperties::stone) + .transform(pickaxeOnly()) + .loot((lt, b) -> lt.add(b, + lt.createSilkTouchDispatchTable(b, + lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.NITRATE) + .apply(ApplyBonusCount.addOreBonusCount(lt.getRegistries().holderOrThrow(Enchantments.FORTUNE))) + )))) + .tag( + BlockTags.NEEDS_IRON_TOOL, + Tags.Blocks.ORES, + Tags.Blocks.ORES_IN_GROUND_STONE, + CNTags.forgeBlockTag("ores/nitrate") + ) + .item() + .tag(Tags.Items.ORES, CNTags.forgeItemTag("ores/nitrate")) + .build() + .register(); + + public static final BlockEntry DEEPSLATE_NITRATE_ORE = CreateNuclear.REGISTRATE + .block("deepslate_nitrate_ore", Block::new) + .initialProperties(SharedProperties::stone) + .simpleItem() + .transform(pickaxeOnly()) + .loot((lt, b) -> lt.add(b, + lt.createSilkTouchDispatchTable(b, + lt.applyExplosionDecay(b, LootItem.lootTableItem(CNItems.NITRATE) + .apply(ApplyBonusCount.addOreBonusCount(lt.getRegistries().holderOrThrow(Enchantments.FORTUNE))) + )))) + .tag( + BlockTags.NEEDS_IRON_TOOL, + Tags.Blocks.ORES, + Tags.Blocks.ORES_IN_GROUND_DEEPSLATE, + CNTags.forgeBlockTag("ores/nitrate") + ) + .item() + .tag(Tags.Items.ORES, CNTags.forgeItemTag("ores/nitrate")) + .build() + .register(); + + public static final BlockEntry RAW_URANIUM_BLOCK = CreateNuclear.REGISTRATE + .block("raw_uranium_block", Block::new) + .initialProperties(SharedProperties::stone) + .transform(pickaxeOnly()) + .tag( + BlockTags.NEEDS_DIAMOND_TOOL, + Tags.Blocks.STORAGE_BLOCKS, + CNTags.forgeBlockTag("storage_blocks/raw_uranium") + ) + .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, c.get()) + .unlockedBy("has_raw_materials_uranium", RegistrateRecipeProvider.has(CNTags.forgeItemTag("raw_materials/uranium"))) + .define('R', CNTags.forgeItemTag("raw_materials/uranium")) + .pattern("RRR") + .pattern("RRR") + .pattern("RRR") + .save(p, CreateNuclear.asResource("crafting/" + c.getName()))) + .item((b, p) -> new UraniumOreItem(b, p, 27)) + .tag( + Tags.Items.STORAGE_BLOCKS, + CNTags.forgeItemTag("storage_blocks/raw_uranium") + ) + .build() + .register(); + + public static final BlockEntry RAW_LEAD_BLOCK = CreateNuclear.REGISTRATE + .block("raw_lead_block", Block::new) + .initialProperties(SharedProperties::stone) + .transform(pickaxeOnly()) + .tag( + Tags.Blocks.STORAGE_BLOCKS, + CNTags.forgeBlockTag("storage_blocks/raw_lead") + ) + .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, c.get()) + .unlockedBy("has_raw_materials_lead", RegistrateRecipeProvider.has(CNTags.forgeItemTag("raw_materials/lead"))) + .define('R', CNTags.forgeItemTag("raw_materials/lead")) + .pattern("RRR") + .pattern("RRR") + .pattern("RRR") + .save(p, CreateNuclear.asResource("crafting/" + c.getName()))) + .item() + .tag( + Tags.Items.STORAGE_BLOCKS, + CNTags.forgeItemTag("storage_blocks/raw_lead") + ) + .build() + .register(); + + + public static final BlockEntry RAW_THORIUM_BLOCK = CreateNuclear.REGISTRATE + .block("raw_thorium_block", Block::new) + .initialProperties(SharedProperties::stone) + .transform(pickaxeOnly()) + .tag( + BlockTags.NEEDS_DIAMOND_TOOL, + Tags.Blocks.STORAGE_BLOCKS, + CNTags.forgeBlockTag("storage_blocks/raw_thorium") + ) + .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, c.get()) + .unlockedBy("has_raw_materials_thorium", RegistrateRecipeProvider.has(CNTags.forgeItemTag("raw_materials/thorium"))) + .define('R', CNTags.forgeItemTag("raw_materials/thorium")) + .pattern("RRR") + .pattern("RRR") + .pattern("RRR") + .save(p, CreateNuclear.asResource("crafting/raw/" + c.getName()))) + .item() + .tag( + Tags.Items.STORAGE_BLOCKS, + CNTags.forgeItemTag("storage_blocks/raw_thorium") + ) + .build() + .register(); + public static final BlockEntry LEAD_BLOCK = CreateNuclear.REGISTRATE + .block("lead_block", Block::new) + .initialProperties(SharedProperties::stone) + .transform(pickaxeOnly()) + .tag( + Tags.Blocks.STORAGE_BLOCKS, + CNTags.forgeBlockTag("storage_blocks/lead") + ) + .item() + .tag( + Tags.Items.STORAGE_BLOCKS, + CNTags.forgeItemTag("storage_blocks/lead") + ) + .build() + .register(); + + public static final BlockEntry THORIUM_BLOCK = CreateNuclear.REGISTRATE + .block("thorium_block", Block::new) + .initialProperties(SharedProperties::stone) + .transform(pickaxeOnly()) + .tag( + Tags.Blocks.STORAGE_BLOCKS, + CNTags.forgeBlockTag("storage_blocks/thorium") + ) + .item() + .tag( + Tags.Items.STORAGE_BLOCKS, + CNTags.forgeItemTag("storage_blocks/thorium") + ) + .build() + .register(); + + public static final BlockEntry STEEL_BLOCK = CreateNuclear.REGISTRATE + .block("steel_block", Block::new) + .initialProperties(SharedProperties::stone) + .transform(pickaxeOnly()) + .tag( + Tags.Blocks.STORAGE_BLOCKS, + CNTags.forgeBlockTag("storage_blocks/steel") + ) + .item() + .tag( + Tags.Items.STORAGE_BLOCKS, + CNTags.forgeItemTag("storage_blocks/steel") + ) + .build() + .register(); public static void register() { CreateNuclear.LOGGER.info("Registering ModBlocks for " + CreateNuclear.MOD_ID); diff --git a/src/main/java/net/nuclearteam/createnuclear/CNClientProxy.java b/src/main/java/net/nuclearteam/createnuclear/CNClientProxy.java new file mode 100644 index 0000000..c27ae50 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/CNClientProxy.java @@ -0,0 +1,68 @@ +package net.nuclearteam.createnuclear; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.*; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance; +import net.minecraft.resources.ResourceLocation; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; + +@OnlyIn(Dist.CLIENT) +public class CNClientProxy { + + public static final ResourceLocation BOMB_FLASH = CreateNuclear.asResource("textures/misc/bomb_flash.png"); + + public static int muteNonNukeSoundsFor = 0; + public static int renderNukeFlashFor = 0; + public static int renderNukeSkyDarkFor = 0; + public static float prevNukeFlashAmount = 0; + public static float nukeFlashAmount = 0; + + public static int lastTremorTick = -1; + public static float[] randomTremorOffsets = new float[3]; + + public static final Int2ObjectMap ENTITY_SOUND_INSTANCE_MAP = new Int2ObjectOpenHashMap<>(); + + public static float getNukeFlashAmount(float partialTicks) { + return prevNukeFlashAmount + (nukeFlashAmount - prevNukeFlashAmount) * partialTicks; + } + + public static void preScreenRender(float partialTick) { + float screenEffectIntensity = Minecraft.getInstance().options.screenEffectScale().get().floatValue(); + float currentNukeFlash = getNukeFlashAmount(partialTick); + + if (currentNukeFlash > 0 && CNConfigs.client().nuclearBombFlash.get()) { + int screenWidth = Minecraft.getInstance().getWindow().getGuiScaledWidth(); + int screenHeight = Minecraft.getInstance().getWindow().getGuiScaledHeight(); + + RenderSystem.disableDepthTest(); + RenderSystem.depthMask(false); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, currentNukeFlash * screenEffectIntensity); + RenderSystem.setShaderTexture(0, BOMB_FLASH); + + Tesselator tesselator = Tesselator.getInstance(); + BufferBuilder bufferbuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); + bufferbuilder.addVertex(0.0F, (float)screenHeight, -90.0F).setUv(0.0F, 1.0F); + bufferbuilder.addVertex((float)screenWidth, (float)screenHeight, -90.0F).setUv(1.0F, 1.0F); + bufferbuilder.addVertex((float)screenWidth, 0.0F, -90.0F).setUv(1.0F, 0.0F); + bufferbuilder.addVertex(0.0F, 0.0F, -90.0F).setUv(0.0F, 0.0F); + BufferUploader.drawWithShader(bufferbuilder.buildOrThrow()); + + RenderSystem.depthMask(true); + RenderSystem.enableDepthTest(); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + } + } + + public static boolean isFarFromCamera(double x, double y, double z) { + return Minecraft.getInstance().gameRenderer.getMainCamera().getPosition().distanceToSqr(x, y, z) >= 256.0D; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/CNDamageTypes.java b/src/main/java/net/nuclearteam/createnuclear/CNDamageTypes.java index 91640cf..6cf5252 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNDamageTypes.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNDamageTypes.java @@ -3,7 +3,9 @@ import net.minecraft.core.registries.Registries; import net.minecraft.data.worldgen.BootstrapContext; import net.minecraft.resources.ResourceKey; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageType; +import net.minecraft.world.level.Level; @SuppressWarnings("unused") public class CNDamageTypes { @@ -11,7 +13,15 @@ private static ResourceKey key(String name) { return ResourceKey.create(Registries.DAMAGE_TYPE, CreateNuclear.asResource(name)); } - public static void bootstrap(BootstrapContext ctx) { + public static final ResourceKey RADIATION = key("radiation"); + public static final ResourceKey FAN_RADIATION = key("fan_radiation"); + + public static DamageSource radiation(Level level) { + return new DamageSource(level.registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(RADIATION)); + } + public static void bootstrap(BootstrapContext ctx) { + ctx.register(RADIATION, new DamageType("radiation", 0.1F)); + ctx.register(FAN_RADIATION, new DamageType("fan_radiation", 0.1F)); } } diff --git a/src/main/java/net/nuclearteam/createnuclear/CNDataComponents.java b/src/main/java/net/nuclearteam/createnuclear/CNDataComponents.java index fc95f9e..4ce2a39 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNDataComponents.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNDataComponents.java @@ -1,13 +1,16 @@ package net.nuclearteam.createnuclear; -import com.simibubi.create.Create; +import com.mojang.serialization.Codec; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.StringRepresentable; import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.network.codec.NeoForgeStreamCodecs; import net.neoforged.neoforge.registries.DeferredRegister; +import net.nuclearteam.createnuclear.content.biome.BiomeIrradiationExtractorItem; +import net.nuclearteam.createnuclear.content.equipment.cloth.ClothItem.ClothItemStack; +import net.nuclearteam.createnuclear.content.equipment.cloth.ClothItem.Cloths; import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintData; import org.jetbrains.annotations.ApiStatus; @@ -16,9 +19,21 @@ public class CNDataComponents { private static final DeferredRegister.DataComponents DATA_COMPONENTS = DeferredRegister.createDataComponents(Registries.DATA_COMPONENT_TYPE, CreateNuclear.MOD_ID); + /** + * Reactor heat stored on the blueprint stack, written by the controller on every tick. + *

+ * Plain {@code Codec.FLOAT}, deliberately not {@code ExtraCodecs.POSITIVE_FLOAT}: zero is + * the normal value for an idle or stopped reactor, and a persistent codec that can reject + * a value crashes the world save rather than the write. That is exactly what happened with + * {@code POSITIVE_FLOAT} ("Value must be positive: 0.0" while serializing the blueprint). + *

+ * The non-negative invariant is enforced upstream instead, where it can't take a save down: + * {@code DefaultHeatCalculator#computeHeat} floors its result at 0. This also matches the + * Forge branch, which stores the value in a plain NBT double. + */ public static final DataComponentType HEAT = register( "heat", - builder -> builder.persistent(ExtraCodecs.POSITIVE_FLOAT).networkSynchronized(ByteBufCodecs.FLOAT) + builder -> builder.persistent(Codec.FLOAT).networkSynchronized(ByteBufCodecs.FLOAT) ); public static final DataComponentType REACTOR_BLUE_PRINT_DATA = register( @@ -26,29 +41,19 @@ public class CNDataComponents { builder -> builder.persistent(ReactorBluePrintData.CODEC).networkSynchronized(ReactorBluePrintData.STREAM_CODEC) ); - public static final DataComponentType PATTERN = register( - "pattern", - builder -> builder.persistent(CompoundTag.CODEC).networkSynchronized(ByteBufCodecs.COMPOUND_TAG) + public static final DataComponentType CLOTH_COLOR = register( + "cloth_color", + b -> b.persistent(StringRepresentable.fromEnum(Cloths::values)).networkSynchronized(NeoForgeStreamCodecs.enumCodec(Cloths.class)) ); - public static final DataComponentType URANIUM_TIME = register( - "uranium_time", - builder -> builder.persistent(ExtraCodecs.NON_NEGATIVE_INT).networkSynchronized(ByteBufCodecs.INT) + public static final DataComponentType CLOTH_ITEM = register( + "cloth_item", + b -> b.persistent(ClothItemStack.CODEC).networkSynchronized(ClothItemStack.STREAM_CODEC) ); - public static final DataComponentType GRAPHITE_TIME = register( - "graphite_time", - builder -> builder.persistent(ExtraCodecs.NON_NEGATIVE_INT).networkSynchronized(ByteBufCodecs.INT) - ); - - public static final DataComponentType COUNT_GRAPHITE_ROD = register( - "count_graphite_rod", - builder -> builder.persistent(ExtraCodecs.NON_NEGATIVE_INT).networkSynchronized(ByteBufCodecs.INT) - ); - - public static final DataComponentType COUNT_URANIUM_ROD = register( - "count_uranium_rod", - builder -> builder.persistent(ExtraCodecs.NON_NEGATIVE_INT).networkSynchronized(ByteBufCodecs.INT) + public static final DataComponentType CHARGE_BIOME_IRRADIATION_EXTRACTOR = register( + BiomeIrradiationExtractorItem.TAG, + builder -> builder.persistent(Codec.INT) ); private static DataComponentType register(String name, UnaryOperator> builder) { diff --git a/src/main/java/net/nuclearteam/createnuclear/CNDisplaySources.java b/src/main/java/net/nuclearteam/createnuclear/CNDisplaySources.java new file mode 100644 index 0000000..def1c7b --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/CNDisplaySources.java @@ -0,0 +1,31 @@ +package net.nuclearteam.createnuclear; + +import com.simibubi.create.api.behaviour.display.DisplaySource; +import com.simibubi.create.foundation.data.CreateRegistrate; +import com.tterrag.registrate.util.entry.RegistryEntry; +import net.nuclearteam.createnuclear.content.redstone.displayLink.source.*; + +import java.util.function.Supplier; + +public class CNDisplaySources { + private static final CreateRegistrate REGISTRATE = CreateNuclear.REGISTRATE; + + public static final RegistryEntry HEAT = simple("heat", HeatDisplaySource::new); + public static final RegistryEntry LIQUID_LEVEL = simple("liquid_level", LiquidLevelDisplaySource::new); + public static final RegistryEntry REACTOR_SUMMARY = simple("reactor_summary", ReactorSummaryDisplaySource::new); + public static final RegistryEntry FUEL = simple("fuel", FuelDisplaySource::new); + public static final RegistryEntry COOLER = simple("cooler", CoolerDisplaySource::new); + public static final RegistryEntry REACTOR_SIZE = simple("reactor_size", ReactorSizeDisplaySource::new); + + /** + * Divergence assumee vs Forge : en 1.21 Registrate type ses entrees + * {@code RegistryEntry} (type du registre + type de l'entree) la ou 1.20.1 + * n'avait que {@code RegistryEntry}. + */ + private static RegistryEntry simple(String name, Supplier supplier) { + return REGISTRATE.displaySource(name, supplier).register(); + } + + public static void register() { + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/CNEffects.java b/src/main/java/net/nuclearteam/createnuclear/CNEffects.java index 1b81995..444a749 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNEffects.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNEffects.java @@ -2,13 +2,13 @@ import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.registries.DeferredRegister; -import net.nuclearteam.createnuclear.content.effects.RadiationEffect; +import net.nuclearteam.createnuclear.content.effects.IodineEffect; +import net.nuclearteam.createnuclear.content.radiation.RadiationEffect; public class CNEffects { public static final DeferredRegister EFFECTS = DeferredRegister.create(BuiltInRegistries.MOB_EFFECT, CreateNuclear.MOD_ID); @@ -18,6 +18,9 @@ public class CNEffects { .addAttributeModifier(Attributes.MOVEMENT_SPEED, CreateNuclear.asResource("radiation"), -0.25f, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL)); + + public static final Holder IODINE = EFFECTS.register("iodine", IodineEffect::new); + public static void register(IEventBus eventBus) { EFFECTS.register(eventBus); }} diff --git a/src/main/java/net/nuclearteam/createnuclear/CNEntityType.java b/src/main/java/net/nuclearteam/createnuclear/CNEntityType.java index ba0a69a..412d90f 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNEntityType.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNEntityType.java @@ -1,6 +1,7 @@ package net.nuclearteam.createnuclear; import com.tterrag.registrate.util.entry.EntityEntry; +import net.minecraft.client.renderer.entity.NoopRenderer; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.storage.loot.LootTable; import net.neoforged.neoforge.client.event.EntityRenderersEvent; @@ -12,13 +13,25 @@ import net.nuclearteam.createnuclear.content.contraptions.irradiated.chicken.IrradiatedChicken; import net.nuclearteam.createnuclear.content.contraptions.irradiated.chicken.IrradiatedChickenModel; import net.nuclearteam.createnuclear.content.contraptions.irradiated.chicken.IrradiatedChickenRenderer; +import net.nuclearteam.createnuclear.content.contraptions.irradiated.cow.IrradiatedCow; +import net.nuclearteam.createnuclear.content.contraptions.irradiated.cow.IrradiatedCowModel; +import net.nuclearteam.createnuclear.content.contraptions.irradiated.cow.IrradiatedCowRenderer; import net.nuclearteam.createnuclear.content.contraptions.irradiated.wolf.IrradiatedWolf; import net.nuclearteam.createnuclear.content.contraptions.irradiated.wolf.IrradiatedWolfModel; import net.nuclearteam.createnuclear.content.contraptions.irradiated.wolf.IrradiatedWolfRenderer; +import net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorModel; +import net.nuclearteam.createnuclear.content.explosion.NuclearExplosionEntity; public class CNEntityType { - public static final EntityEntry IRRADIATED_CAT = CreateNuclear.REGISTRATE + public static final EntityEntry NUCLEAR_EXPLOSION = CreateNuclear.REGISTRATE + .entity("nuclear_explosion", NuclearExplosionEntity::new, MobCategory.MISC) + .properties(p -> p.sized(1.0f, 1.0f)) + .lang("Nuclear Explosion") + .renderer(() -> NoopRenderer::new) + .register(); + + public static final EntityEntry IRRADIATED_CAT = CreateNuclear.REGISTRATE .entity("irradiated_cat", IrradiatedCat::new, MobCategory.CREATURE) .loot((tb, e) -> tb.add(e, LootTable.lootTable())) .tag(CNEntityTags.IRRADIATED_IMMUNE.tag) @@ -38,20 +51,33 @@ public class CNEntityType { .attributes(IrradiatedChicken::createAttributes) .register(); - public static final EntityEntry IRRADIATED_WOLF = CreateNuclear.REGISTRATE + public static final EntityEntry IRRADIATED_WOLF = CreateNuclear.REGISTRATE .entity("irradiated_wolf", IrradiatedWolf::new, MobCategory.CREATURE) .loot((tb, e) -> tb.add(e, LootTable.lootTable())) .tag(CNEntityTags.IRRADIATED_IMMUNE.tag) - .properties(p -> p.sized(0.6f, 0.85f)) + .properties(p -> p.sized(0.6f, 0.85f).eyeHeight(0.68f)) .lang("Irradiated Wolf") .renderer(() -> IrradiatedWolfRenderer::new) .attributes(IrradiatedWolf::createAttributes) .register(); + public static final EntityEntry IRRADIATED_COW = CreateNuclear.REGISTRATE + .entity("irradiated_cow", IrradiatedCow::new, MobCategory.CREATURE) + .loot((tb, e) -> tb.add(e, LootTable.lootTable())) + .tag(CNEntityTags.IRRADIATED_IMMUNE.tag) + .properties(p -> p.sized(0.6f, 0.85f)) + .lang("Irradiated Cow") + .renderer(() -> IrradiatedCowRenderer::new) + .attributes(IrradiatedCow::createAttributes) + .register(); + public static void registerModelLayer(EntityRenderersEvent.RegisterLayerDefinitions event) { event.registerLayerDefinition(CNModelLayers.IRRADIATED_CAT, IrradiatedCatModel::createBodyLayer); event.registerLayerDefinition(CNModelLayers.IRRADIATED_CHICKEN, IrradiatedChickenModel::createBodyLayer); event.registerLayerDefinition(CNModelLayers.IRRADIATED_WOLF, IrradiatedWolfModel::createBodyLayer); + event.registerLayerDefinition(CNModelLayers.IRRADIATED_COW, IrradiatedCowModel::createBodyLayer); + + event.registerLayerDefinition(CNModelLayers.ANTI_RADIATION_ARMOR, AntiRadiationArmorModel::createBodyLayer); } public static void register() {} diff --git a/src/main/java/net/nuclearteam/createnuclear/CNFluids.java b/src/main/java/net/nuclearteam/createnuclear/CNFluids.java index c5f6ebe..609ded4 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNFluids.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNFluids.java @@ -5,12 +5,24 @@ import com.tterrag.registrate.util.entry.FluidEntry; import net.createmod.catnip.theme.Color; import net.minecraft.core.BlockPos; +import net.minecraft.core.dispenser.BlockSource; +import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; +import net.minecraft.core.dispenser.DispenseItemBehavior; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BucketItem; +import net.minecraft.world.item.DispensibleContainerItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.DispenserBlock; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; import net.neoforged.neoforge.common.NeoForgeMod; import net.neoforged.neoforge.common.SoundActions; @@ -21,47 +33,143 @@ import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.nuclearteam.createnuclear.content.decoration.palettes.CNPaletteStoneTypes; +import net.nuclearteam.createnuclear.content.radiation.capability.RadiationCapability; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancement; import org.joml.Vector3f; import net.nuclearteam.createnuclear.CNTags.CNFluidTags; import java.util.List; import java.util.function.Supplier; +import net.nuclearteam.createnuclear.content.radiation.RadiationBucketItem; + public class CNFluids { + private static final double URANIUM_FLUID_DOSE = 5.0D; + public static final FluidEntry URANIUM = - CreateNuclear.REGISTRATE.standardFluid("uranium", SolidRenderedPlaceableFluidity.create(0x38FF08, () -> 1f / 32f)) - .lang("Liquid Uranium") - //.tag(CNFluidTags.URANIUM.tag) - .properties(p -> p.viscosity(2500) - .density(1600) - .canSwim(false) - .sound(SoundActions.BUCKET_FILL, SoundEvents.BUCKET_FILL_LAVA) - .sound(SoundActions.BUCKET_EMPTY, SoundEvents.BUCKET_EMPTY_LAVA) - .canDrown(false) - ) - .fluidProperties(f -> f.levelDecreasePerBlock(2) - .tickRate(15) - .slopeFindDistance(6) - .explosionResistance(100f) - ) - .source(BaseFlowingFluid.Source::new) - .bucket() - //.tag(CNTags.forgeItemTag("buckets/uranium")) - .lang("Uranium Bucket") - .build() - .register(); + CreateNuclear.REGISTRATE.standardFluid("uranium", SolidRenderedPlaceableFluidity.create(0x38FF08, () -> 1f / 32f)) + .lang("Liquid Uranium") + .tag(CNFluidTags.URANIUM.tag) + .properties(p -> p.viscosity(2500) + .density(1600) + .canSwim(false) + .sound(SoundActions.BUCKET_FILL, SoundEvents.BUCKET_FILL_LAVA) + .sound(SoundActions.BUCKET_EMPTY, SoundEvents.BUCKET_EMPTY_LAVA) + .canDrown(false) + ) + .fluidProperties(f -> f.levelDecreasePerBlock(2) + .tickRate(15) + .slopeFindDistance(6) + .explosionResistance(100f) + ) + .source(BaseFlowingFluid.Source::new) + .bucket((s, p) -> new RadiationBucketItem(s instanceof Fluid ? (Fluid) s : ((Supplier) s).get(), p, 20)) + .onRegister(CNFluids::registerFluidDispenseBehavior) + .tag(CNTags.forgeItemTag("buckets/uranium")) + .lang("Uranium Bucket") + .build() + .register(); + + public static final FluidEntry THORIUM = + CreateNuclear.REGISTRATE.standardFluid("thorium", SolidRenderedPlaceableFluidity.create(0x38f9ff, () -> 1f / 32f)) + .lang("Liquid Thorium") + .tag(CNFluidTags.THORIUM.tag) + .properties(p -> p.viscosity(200) + .density(100) + .canSwim(false) + .sound(SoundActions.BUCKET_FILL, SoundEvents.BUCKET_FILL_LAVA) + .sound(SoundActions.BUCKET_EMPTY, SoundEvents.BUCKET_EMPTY_LAVA) + .canDrown(false) + ) + .fluidProperties(f -> f.levelDecreasePerBlock(2) + .tickRate(15) + .slopeFindDistance(6) + .explosionResistance(100f) + ) + .source(BaseFlowingFluid.Source::new) + .bucket() + .onRegister(CNFluids::registerFluidDispenseBehavior) + .tag(CNTags.forgeItemTag("buckets/thorium")) + .lang("Thorium Bucket") + .build() + .register(); + + public static final FluidEntry LIQUID_NITROGEN = + CreateNuclear.REGISTRATE.standardFluid("nitrogen", SolidRenderedPlaceableFluidity.create(0x23ECD5, () -> 1f / 16f)) + .lang("Liquid Nitrogen") + .tag(CNFluidTags.NITROGEN.tag) + .properties(p -> p.viscosity(1000) + .density(1000) + .canSwim(true) + .sound(SoundActions.BUCKET_FILL, SoundEvents.BUCKET_FILL_AXOLOTL) + .sound(SoundActions.BUCKET_EMPTY, SoundEvents.BUCKET_EMPTY_FISH) + .canDrown(false) + ) + .fluidProperties(f -> f.levelDecreasePerBlock(5) + .tickRate(10) + .slopeFindDistance(6) + .explosionResistance(100f) + ) + .source(BaseFlowingFluid.Source::new) + //.onRegister(ReactorFluidTypesValue.setReactorFluidTypeInfos(8196, 100)) + .bucket() + .onRegister(CNFluids::registerFluidDispenseBehavior) + .lang("Nitrogen Bucket") + .tag(CNTags.forgeItemTag("buckets/nitrogen")) + .build() + .register(); + public static void register() {} - public static void handleFluidEffect(LivingEvent.LivingVisibilityEvent event) { + public static void handleFluidEffect(LivingEvent.LivingVisibilityEvent event) { LivingEntity entity = event.getEntity(); - if (entity.isAlive() && !(entity.isSpectator())) { - if (entity.tickCount % 20 == 0) return; - if (entity.isInFluidType(URANIUM.getType())) { - entity.addEffect(new MobEffectInstance(CNEffects.RADIATION.getDelegate(), 100, 0)); + if (!entity.isAlive() || entity.isSpectator()) return; + + Level level = entity.level(); + + // 1. Uranium: applies radiation contagion + if (entity.isInFluidType(URANIUM.getType())) { + if (entity.tickCount % 20 == 0) { + RadiationCapability.applyContagion(entity, URANIUM_FLUID_DOSE, 100); } } + // 2. Liquid nitrogen: freezes the entity like powder snow + else if (entity.isInFluidType(LIQUID_NITROGEN.getType())) { + // Extinguish fire immediately on contact + if (entity.isOnFire()) { + entity.clearFire(); + } + + if (entity instanceof Player player && player.isSwimming()) { + CNAdvancement.CRYOGENIC_BAPTISM.awardTo(player); + } + + int currentTicks = entity.getTicksFrozen(); + int maxTicks = entity.getTicksRequiredToFreeze(); + int freezeSpeed = 3; + + if (level.isClientSide) { + // Target maxTicks + 1 so vanilla's client-side -1 decay settles exactly at maxTicks + entity.setTicksFrozen(Math.min(maxTicks + 1, currentTicks + freezeSpeed + 1)); + } else { + // Target maxTicks + 2 so vanilla's server-side -2 decay settles exactly at maxTicks + entity.setTicksFrozen(Math.min(maxTicks + 2, currentTicks + freezeSpeed + 2)); + + // Check the freeze state after applying the compensation above + if (entity.getTicksFrozen() >= maxTicks && entity.tickCount % 10 == 0) { + entity.hurt(entity.damageSources().freeze(), 2.0F); + } + + entity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 40, 1, true, false, false)); + } + } + + // 3. Thorium: burns the entity like lava + else if (entity.isInFluidType(THORIUM.getType())) { + entity.lavaHurt(); + } } public static void registerFluidInteractions() { @@ -73,8 +181,8 @@ public static void registerFluidInteractions() { // List of source FluidTypes we want to register (lava and water) List sourceFluids = List.of( - NeoForgeMod.LAVA_TYPE.value(), - NeoForgeMod.WATER_TYPE.value() + NeoForgeMod.LAVA_TYPE.value(), + NeoForgeMod.WATER_TYPE.value() ); // Loop over each source fluid and register the interaction @@ -86,17 +194,20 @@ public static void registerFluidInteractions() { private static class SolidRenderedPlaceableFluidity extends AllFluids.TintedFluidType { private Vector3f fogColor; + private int fogIntColor; private Supplier fogDistance; public static FluidTypeFactory create(int fogColor, Supplier fogDistance) { return (p, s, f) -> { SolidRenderedPlaceableFluidity fluidtype = new SolidRenderedPlaceableFluidity(p,s,f); fluidtype.fogColor = new Color(fogColor, false).asVectorF(); + fluidtype.fogIntColor = fogColor; fluidtype.fogDistance = fogDistance; return fluidtype; }; } + private SolidRenderedPlaceableFluidity(Properties properties, ResourceLocation stillTecture, ResourceLocation flowingTexture) { super(properties, stillTecture, flowingTexture); } @@ -108,7 +219,7 @@ protected int getTintColor(FluidStack stack) { @Override protected int getTintColor(FluidState state, BlockAndTintGetter getter, BlockPos pos) { - return 0x38FF08; + return fogIntColor; } @Override @@ -121,4 +232,22 @@ protected float getFogDistanceModifier() { return fogDistance.get(); } } + + private static final DispenseItemBehavior DEFAULT = new DefaultDispenseItemBehavior(); + private static final DispenseItemBehavior DISPENSE_FLUID = new DefaultDispenseItemBehavior(){ + @Override + protected ItemStack execute(BlockSource pSource, ItemStack pStack) { + DispensibleContainerItem dispensibleContainerItem = (DispensibleContainerItem) pStack.getItem(); + BlockPos pos = pSource.pos().relative(pSource.state().getValue(DispenserBlock.FACING)); + Level level = pSource.level(); + if (dispensibleContainerItem.emptyContents(null, level, pos, null, pStack)) { + return new ItemStack(Items.BUCKET); + } + return DEFAULT.dispense(pSource, pStack); + } + }; + + private static void registerFluidDispenseBehavior(BucketItem bucket) { + DispenserBlock.registerBehavior(bucket, DISPENSE_FLUID); + } } diff --git a/src/main/java/net/nuclearteam/createnuclear/CNItems.java b/src/main/java/net/nuclearteam/createnuclear/CNItems.java index fb0cbbe..f406937 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNItems.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNItems.java @@ -1,14 +1,9 @@ package net.nuclearteam.createnuclear; -import static net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem.Boot; -import static net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem.Chestplate; -import static net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem.Chestplate.getChestplateTag; -import static net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem.Helmet; -import static net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem.Helmet.getHelmetTag; -import static net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem.Leggings; - import static net.nuclearteam.createnuclear.CNTags.CNItemTags; -import static net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem.Leggings.getLeggingsTag; +import static net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem.*; +import static net.nuclearteam.createnuclear.foundation.data.CNBuilderTransformers.biomeRestoreModel; +import static net.nuclearteam.createnuclear.foundation.data.CNBuilderTransformers.coloredArmorModel; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; @@ -17,27 +12,29 @@ import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.data.recipes.ShapelessRecipeBuilder; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.Mob; import net.minecraft.world.food.FoodProperties; -import net.minecraft.world.item.ArmorItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.Items; +import net.minecraft.world.item.*; +import net.minecraft.world.item.crafting.Ingredient; import net.neoforged.neoforge.common.DeferredSpawnEggItem; -import net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem; +import net.neoforged.neoforge.common.Tags; +import net.nuclearteam.createnuclear.api.ItemRodTypesValue; +import net.nuclearteam.createnuclear.api.data.recipe.SmithingClothRecipeBuilder; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; +import net.nuclearteam.createnuclear.content.biome.BiomeIrradiationExtractorItem; import net.nuclearteam.createnuclear.content.equipment.armor.CNArmorMaterials; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; import net.nuclearteam.createnuclear.content.equipment.cloth.ClothItem; -import net.nuclearteam.createnuclear.content.equipment.cloth.ClothItem.DyeItemList; +import net.nuclearteam.createnuclear.content.equipment.cloth.ClothItem.Cloths; import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintItem; +import net.nuclearteam.createnuclear.content.radiation.RadiationItem; +import net.nuclearteam.createnuclear.foundation.data.CNBuilderTransformers; import net.nuclearteam.createnuclear.foundation.item.DyedItemsList; import net.nuclearteam.createnuclear.foundation.utility.TextUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.function.Supplier; @SuppressWarnings({"unused", "deprecation"}) public class CNItems { @@ -45,9 +42,9 @@ public class CNItems { CreateNuclear.REGISTRATE.setCreativeTab(CNCreativeModeTabs.MAIN); } - public static final ItemEntry + public static final ItemEntry YELLOWCAKE = CreateNuclear.REGISTRATE - .item("yellowcake", Item::new) + .item("yellowcake", p -> new RadiationItem(p, 4)) .properties(p -> p.food(new FoodProperties.Builder() .nutrition(20) .saturationModifier(0.3F) @@ -57,217 +54,354 @@ public class CNItems { ) .register(), - RAW_LEAD = CreateNuclear.REGISTRATE - .item("raw_lead", Item::new) - .tag(CNTags.forgeItemTag("raw_ores"), CNTags.forgeItemTag("raw_materials"), CNTags.forgeItemTag("raw_materials/lead")) - .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) - .unlockedBy("has_storage_blocks_raw_lead", RegistrateRecipeProvider.has(CNTags.forgeItemTag("storage_blocks/raw_lead"))) - .requires(CNTags.forgeItemTag("storage_blocks/raw_lead")) - .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) - ) + ENRICHED_YELLOWCAKE = CreateNuclear.REGISTRATE + .item("enriched_yellowcake", p -> new RadiationItem(p, 2)) .register(), RAW_URANIUM = CreateNuclear.REGISTRATE - .item("raw_uranium", Item::new) - .tag(CNTags.forgeItemTag("raw_ores"), CNTags.forgeItemTag("raw_materials"), CNTags.forgeItemTag("raw_materials/uranium")) - .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) - .unlockedBy("has_storage_blocks_raw_uranium", RegistrateRecipeProvider.has(CNTags.forgeItemTag("storage_blocks/raw_uranium"))) - .requires(CNTags.forgeItemTag("storage_blocks/raw_uranium")) - .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) - ) + .item("raw_uranium", p -> new RadiationItem(p, 3)) + .tag(CNTags.forgeItemTag("raw_ores"), Tags.Items.RAW_MATERIALS, CNTags.forgeItemTag("raw_materials/uranium")) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) + .unlockedBy("has_storage_blocks_raw_uranium", RegistrateRecipeProvider.has(CNTags.forgeItemTag("storage_blocks/raw_uranium"))) + .requires(CNTags.forgeItemTag("storage_blocks/raw_uranium")) + .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) + ) .register(), URANIUM_POWDER = CreateNuclear.REGISTRATE - .item("uranium_powder", Item::new) - .tag(CNTags.forgeItemTag("dusts"), CNTags.forgeItemTag("dusts/uranium")) + .item("uranium_powder", p -> new RadiationItem(p, 2)) + .tag(Tags.Items.DUSTS, CNTags.forgeItemTag("dusts/uranium")) + .register(), + + URANIUM_ROD = CreateNuclear.REGISTRATE + .item("uranium_rod", p -> new RadiationItem(p, 100)) + .onRegister(ItemRodTypesValue.setRodTypeInfos(new RodType.Builder() + .baseRodHeat(() -> CNConfigs.server().rods.uraniumBaseValue.get()) + .proximityRodHeat(() -> (float) CNConfigs.server().rods.uraniumProximityBonus.get()) + .rodTimer(() -> CNConfigs.server().rods.uraniumRodLifetime.get()) + .ratio(() -> CNConfigs.server().rods.uraniumHeatRatio.get()) + .fuelRodType())) + .tag(Tags.Items.RODS, CNItemTags.FUEL.tag) + .register(); + + public static final ItemEntry + RAW_LEAD = CreateNuclear.REGISTRATE + .item("raw_lead", Item::new) + .tag(CNTags.forgeItemTag("raw_ores"), Tags.Items.RAW_MATERIALS, CNTags.forgeItemTag("raw_materials/lead")) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) + .unlockedBy("has_storage_blocks_raw_lead", RegistrateRecipeProvider.has(CNTags.forgeItemTag("storage_blocks/raw_lead"))) + .requires(CNTags.forgeItemTag("storage_blocks/raw_lead")) + .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) + ) .register(), STEEL_INGOT = CreateNuclear.REGISTRATE .item("steel_ingot", Item::new) - .tag(CNTags.forgeItemTag("ingots"), CNTags.forgeItemTag("ingots/steel")) - .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) - .unlockedBy("has_storage_blocks_steel", RegistrateRecipeProvider.has(CNTags.forgeItemTag("storage_blocks/steel"))) - .requires(CNTags.forgeItemTag("storage_blocks/steel")) - .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) - ) + .tag(Tags.Items.INGOTS, CNTags.forgeItemTag("ingots/steel")) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) + .unlockedBy("has_storage_blocks_steel", RegistrateRecipeProvider.has(CNTags.forgeItemTag("storage_blocks/steel"))) + .requires(CNTags.forgeItemTag("storage_blocks/steel")) + .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) + ) .register(), COAL_DUST = CreateNuclear.REGISTRATE .item("coal_dust", Item::new) - .tag(CNTags.forgeItemTag("dusts"), CNTags.forgeItemTag("dusts/coal")) + .tag(Tags.Items.DUSTS, CNTags.forgeItemTag("dusts/coal")) .register(), GRAPHITE_ROD = CreateNuclear.REGISTRATE .item("graphite_rod", Item::new) - .tag(CNTags.forgeItemTag("rods"), CNItemTags.COOLER.tag) + .onRegister(ItemRodTypesValue.setRodTypeInfos(new RodType.Builder() + .baseRodHeat(() -> CNConfigs.server().rods.graphiteBaseValue.get()) + .proximityRodHeat(() -> CNConfigs.server().rods.graphiteProximityMalus.getF()) + .rodTimer(() -> CNConfigs.server().rods.graphiteRodLifetime.get()) + .ratio(() -> CNConfigs.server().rods.graphiteHeatRatio.get()) + .coolerRodType())) + .tag(Tags.Items.RODS, CNItemTags.COOLER.tag) .register(), LEAD_INGOT = CreateNuclear.REGISTRATE .item("lead_ingot", Item::new) - .tag(CNTags.forgeItemTag("ingots"), CNTags.forgeItemTag("ingots/lead")) - .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(),9) - .unlockedBy("has_storage_blocks_lead", RegistrateRecipeProvider.has(CNTags.forgeItemTag("storage_blocks/lead"))) - .requires(CNTags.forgeItemTag("storage_blocks/lead")) - .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) - ) + .tag(Tags.Items.INGOTS, CNTags.forgeItemTag("ingots/lead")) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(),9) + .unlockedBy("has_storage_blocks_lead", RegistrateRecipeProvider.has(CNTags.forgeItemTag("storage_blocks/lead"))) + .requires(CNTags.forgeItemTag("storage_blocks/lead")) + .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) + ) .register(), STEEL_NUGGET = CreateNuclear.REGISTRATE .item("steel_nugget", Item::new) - .tag(CNTags.forgeItemTag("nuggets"), CNTags.forgeItemTag("nuggets/steel")) - .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) - .unlockedBy("has_storage_blocks_steel_nugget", RegistrateRecipeProvider.has(CNTags.forgeItemTag("ingots/steel"))) - .requires(CNTags.forgeItemTag("ingots/steel")) - .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) - ) - .register(), - - URANIUM_ROD = CreateNuclear.REGISTRATE - .item("uranium_rod", Item::new) - .tag(CNTags.forgeItemTag("rods"), CNItemTags.FUEL.tag) + .tag(Tags.Items.NUGGETS, CNTags.forgeItemTag("nuggets/steel")) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) + .unlockedBy("has_storage_blocks_steel_nugget", RegistrateRecipeProvider.has(CNTags.forgeItemTag("ingots/steel"))) + .requires(CNTags.forgeItemTag("ingots/steel")) + .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) + ) .register(), LEAD_NUGGET = CreateNuclear.REGISTRATE .item("lead_nugget", Item::new) - .tag(CNTags.forgeItemTag("nuggets"), CNTags.forgeItemTag("nuggets/lead")) - .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) - .unlockedBy("has_storage_blocks_lead_nugget", RegistrateRecipeProvider.has(CNTags.forgeItemTag("ingots/lead"))) - .requires(CNTags.forgeItemTag("ingots/lead")) - .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) - ) + .tag(Tags.Items.NUGGETS, CNTags.forgeItemTag("nuggets/lead")) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) + .unlockedBy("has_storage_blocks_lead_nugget", RegistrateRecipeProvider.has(CNTags.forgeItemTag("ingots/lead"))) + .requires(CNTags.forgeItemTag("ingots/lead")) + .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) + ) .register(), GRAPHENE = CreateNuclear.REGISTRATE .item("graphene", Item::new) .register(), - ENRICHED_YELLOWCAKE = CreateNuclear.REGISTRATE - .item("enriched_yellowcake", Item::new) - .register() - ; + RAW_THORIUM = CreateNuclear.REGISTRATE + .item("raw_thorium", Item::new) + .tag(CNTags.forgeItemTag("raw_ores"), Tags.Items.RAW_MATERIALS, CNTags.forgeItemTag("raw_materials/thorium")) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) + .unlockedBy("has_storage_blocks_raw_thorium", RegistrateRecipeProvider.has(CNTags.forgeItemTag("storage_blocks/raw_thorium"))) + .requires(CNTags.forgeItemTag("storage_blocks/raw_thorium")) + .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) + ) + .register(), - public static final DyedItemsList ANTI_RADIATION_HELMETS = new DyedItemsList<>(color -> { - String colorName = color.getSerializedName(); - return CreateNuclear.REGISTRATE.item(colorName + "_anti_radiation_helmet", p -> new Helmet(p, color)) - .tag( - CNTags.forgeItemTag("armors/helmets"), - getHelmetTag(colorName), - CNItemTags.ALL_ANTI_RADIATION_ARMORS.tag, - CNItemTags.ANTI_RADIATION_HELMET_FULL_DYE.tag + THORIUM_DUST = CreateNuclear.REGISTRATE + .item("thorium_dust", Item::new) + .tag(Tags.Items.DUSTS, CNTags.forgeItemTag("dusts/thorium")) + .register(), + + THORIUM_NUGGET = CreateNuclear.REGISTRATE + .item("thorium_nugget", Item::new) + .model((c, p) -> p.generated(c, CreateNuclear.asResource("item/thorium_nugget"))) + .tag(Tags.Items.NUGGETS, CNTags.forgeItemTag("nuggets/thorium")) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) + .unlockedBy("has_storage_blocks_steel_nugget", RegistrateRecipeProvider.has(CNTags.forgeItemTag("ingots/thorium"))) + .requires(CNTags.forgeItemTag("ingots/thorium")) + .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) ) - .recipe((c, p) -> - ShapedRecipeBuilder.shaped(RecipeCategory.COMBAT, c.get()) - .unlockedBy("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) - .define('X', CNTags.forgeItemTag("ingots/lead")) - .define('Y', ClothItem.Cloths.getByColor(color).get()) - .define('Z', CNBlocks.REINFORCED_GLASS.asItem()) - .pattern("YXY") - .pattern("XZX") - .showNotification(true) - .save(p, CreateNuclear.asResource("crafting/items/armors/" + c.getName()))) - - .properties(p -> p.durability(CNArmorMaterials.durabilityForType(ArmorItem.Type.HELMET))) - .lang(TextUtils.titleCaseConversion(color.getName()) +" Anti Radiation Helmet") - .model((c, p) -> p.generated(c, CreateNuclear.asResource("item/armors/helmets/" + colorName + "_anti_radiation_helmet"))) - .register(); + .register(), - }); + THORIUM_INGOT = CreateNuclear.REGISTRATE + .item("thorium_ingot", Item::new) + .model((c, p) -> p.generated(c, CreateNuclear.asResource("item/thorium_ingot"))) + .tag(Tags.Items.INGOTS, CNTags.forgeItemTag("ingots/thorium")) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get(), 9) + .unlockedBy("has_storage_blocks_thorium", RegistrateRecipeProvider.has(CNTags.forgeItemTag("storage_blocks/thorium"))) + .requires(CNTags.forgeItemTag("storage_blocks/thorium")) + .save(p, CreateNuclear.asResource("crafting/" + c.getName() + "_from_decompacting")) + ) + .register(), - public static final DyedItemsList ANTI_RADIATION_CHESTPLATES = new DyedItemsList<>(color -> { - String colorName = color.getSerializedName(); + THORIUM_ROD = CreateNuclear.REGISTRATE + .item("thorium_rod", Item::new) + .onRegister(ItemRodTypesValue.setRodTypeInfos(new RodType.Builder() + .baseRodHeat(() -> CNConfigs.server().rods.baseValueThorium.get()) + .proximityRodHeat(() -> (float) CNConfigs.server().rods.thoriumProxyBonus.get()) + .rodTimer(() -> CNConfigs.server().rods.thoriumRodLifetime.get()) + .ratio(() -> CNConfigs.server().rods.thoriumHeatRatio.get()) + .fuelRodType())) + .tag(Tags.Items.RODS, CNItemTags.FUEL.tag) + .register(), - return CreateNuclear.REGISTRATE.item(colorName + "_anti_radiation_chestplate", p -> new Chestplate(p, color)) + NITRATE = CreateNuclear.REGISTRATE + .item("nitrate", Item::new) + .lang("Nitrate") + .register(), + + NITROGEN_CONCENTRATE = CreateNuclear.REGISTRATE + .item("nitrogen_concentrate", Item::new) + .lang("Nitrogen Concentrate") + .register(), + + COOLED_NITROGEN_CONCENTRATE = CreateNuclear.REGISTRATE + .item("cooled_nitrogen_concentrate", Item::new) + .lang("Cooled Nitrogen Concentrate") + .register() + ; + + public static final ItemEntry ANTI_RADIATION_HELMETS = CreateNuclear.REGISTRATE + .item("default_anti_radiation_helmet", Helmet::new) + .properties(p -> p.stacksTo(1)) + .tag( + Tags.Items.ARMORS, + CNTags.forgeItemTag("armors/helmets"), + CNItemTags.ANTI_RADIATION_ARMOR.tag, + CNItemTags.ANTI_RADIATION_HELMET.tag + ) + .transform(setColorComponent(Cloths.DEFAULT)) + .transform(CNArmorMaterials.setArmorDurability(Type.HELMET)) + .recipe((c, p) -> { + ShapedRecipeBuilder.shaped(RecipeCategory.COMBAT, c.get()) + .unlockedBy("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) + .define('X', CNTags.forgeItemTag("ingots/lead")) + .define('Y', CNTags.forgeItemTag("ingots/brass")) + .define('Z', CNBlocks.REINFORCED_GLASS.asItem()) + .pattern("YXY") + .pattern("XZX") + .showNotification(true) + .save(p, CreateNuclear.asResource("crafting/items/armors/" + c.getName())); + + for (Cloths cloth : Cloths.values()) { + if (cloth == Cloths.DEFAULT) continue; + SmithingClothRecipeBuilder + .smithingCloth( + Ingredient.EMPTY, + Ingredient.of(c.get()), + Ingredient.of(cloth.getItem()), + RecipeCategory.COMBAT, + new ItemStack(c.get()) + ) + .unlocks("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) + .save(p, CreateNuclear.asResource("smithing/" + c.getName() + "_" + cloth.getSerializedName())); + } + }) + .lang("Anti Radiation Helmet") + .model(coloredArmorModel("helmet", "layer0", "particle")) + .register(); + + public static final ItemEntry ANTI_RADIATION_CHESTPLATES = CreateNuclear.REGISTRATE + .item("default_anti_radiation_chestplate", Chestplate::new) + .properties(p -> p.stacksTo(1)) .tag( + Tags.Items.ARMORS, CNTags.forgeItemTag("armors/chestplates"), - getChestplateTag(colorName), - CNItemTags.ALL_ANTI_RADIATION_ARMORS.tag, - CNItemTags.ANTI_RADIATION_CHESTPLATE_FULL_DYE.tag + CNTags.CNItemTags.ANTI_RADIATION_ARMOR.tag ) - .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.COMBAT, c.get()) - .unlockedBy("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) - .define('X', CNTags.forgeItemTag("ingots/lead")) - .define('Y', ClothItem.Cloths.getByColor(color).get()) - .define('Z', CNItems.GRAPHITE_ROD) - .pattern("Y Y") - .pattern("XXX") - .pattern("ZXZ") - .showNotification(true) - .save(p, CreateNuclear.asResource("crafting/items/armors/" + c.getName()))) - - .properties(p -> p.durability(CNArmorMaterials.durabilityForType(ArmorItem.Type.CHESTPLATE))) - .lang(TextUtils.titleCaseConversion(color.getName()) +" Anti Radiation Chestplate") - .model((c, p) -> p.generated(c, CreateNuclear.asResource("item/armors/chestplates/" + colorName + "_anti_radiation_chestplate"))) + .transform(setColorComponent(Cloths.DEFAULT)) + .transform(CNArmorMaterials.setArmorDurability(Type.CHESTPLATE)) + .recipe((c, p) -> { + ShapedRecipeBuilder.shaped(RecipeCategory.COMBAT, c.get()) + .unlockedBy("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) + .define('X', CNTags.forgeItemTag("ingots/lead")) + .define('Y', CNTags.forgeItemTag("ingots/brass")) + .define('Z', CNItems.GRAPHITE_ROD) + .pattern("Y Y") + .pattern("XXX") + .pattern("ZXZ") + .showNotification(true) + .save(p, CreateNuclear.asResource("crafting/items/armors/" + c.getName())); + for (Cloths cloth : Cloths.values()) { + if (cloth == Cloths.DEFAULT) continue; + + SmithingClothRecipeBuilder + .smithingCloth( + Ingredient.EMPTY, + Ingredient.of(c.get()), + Ingredient.of(cloth.getItem()), + RecipeCategory.COMBAT, + new ItemStack(c.get()) + ) + .unlocks("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) + .save(p, CreateNuclear.asResource("smithing/" + c.getName() + "_" + cloth.getSerializedName())); + } + }) + .lang("Anti Radiation Chestplate") + .model(coloredArmorModel("chestplate", "14")) .register(); - }); - - public static final DyedItemsList ANTI_RADIATION_LEGGINGS = new DyedItemsList<>(color -> { - String colorName = color.getSerializedName(); - return CreateNuclear.REGISTRATE.item(colorName + "_anti_radiation_leggings", p -> new Leggings(p, color)) + public static final ItemEntry ANTI_RADIATION_LEGGINGS = CreateNuclear.REGISTRATE + .item("default_anti_radiation_leggings", Leggings::new) + .properties(p -> p.stacksTo(1)) .tag( + Tags.Items.ARMORS, CNTags.forgeItemTag("armors/leggings"), - getLeggingsTag(colorName), - CNItemTags.ALL_ANTI_RADIATION_ARMORS.tag, - CNItemTags.ANTI_RADIATION_LEGGINGS_FULL_DYE.tag + CNTags.CNItemTags.ANTI_RADIATION_ARMOR.tag ) - .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.COMBAT, c.get()) - .unlockedBy("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) - .define('X', CNTags.forgeItemTag("ingots/lead")) - .define('Y', ClothItem.Cloths.getByColor(color).get()) - .pattern("YXY") - .pattern("X X") - .pattern("Y Y") - .showNotification(true) - .save(p, CreateNuclear.asResource("crafting/items/armors/" + c.getName()))) - - .properties(p -> p.durability(CNArmorMaterials.durabilityForType(ArmorItem.Type.LEGGINGS))) - .lang(TextUtils.titleCaseConversion(color.getName()) +" Anti Radiation Leggings") - .model((c, p) -> p.generated(c, CreateNuclear.asResource("item/armors/leggings/" + colorName + "_anti_radiation_leggings"))) + .transform(setColorComponent(Cloths.DEFAULT)) + .transform(CNArmorMaterials.setArmorDurability(Type.LEGGINGS)) + .recipe((c, p) -> { + ShapedRecipeBuilder.shaped(RecipeCategory.COMBAT, c.get()) + .unlockedBy("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) + .define('X', CNTags.forgeItemTag("ingots/lead")) + .define('Y', CNTags.forgeItemTag("ingots/brass")) + .pattern("YXY") + .pattern("X X") + .pattern("Y Y") + .showNotification(true) + .save(p, CreateNuclear.asResource("crafting/items/armors/" + c.getName())); + + for (Cloths cloth : Cloths.values()) { + if (cloth == Cloths.DEFAULT) continue; + + SmithingClothRecipeBuilder + .smithingCloth( + Ingredient.EMPTY, + Ingredient.of(c.get()), + Ingredient.of(cloth.getItem()), + RecipeCategory.COMBAT, + new ItemStack(c.get()) + ) + .unlocks("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) + .save(p, CreateNuclear.asResource("smithing/" + c.getName() + "_" + cloth.getSerializedName())); + } + }) + .lang("Anti Radiation Leggings") + .model(coloredArmorModel("leggings", "14")) .register(); - }); - - public static final ItemEntry - ANTI_RADIATION_BOOTS = CreateNuclear.REGISTRATE.item("anti_radiation_boots", Boot::new) + public static final ItemEntry ANTI_RADIATION_BOOTS = CreateNuclear.REGISTRATE + .item("default_anti_radiation_boots", Boot::new) + .properties(p -> p.stacksTo(1)) .tag( + Tags.Items.ARMORS, CNTags.forgeItemTag("armors/boots"), - CNItemTags.ANTI_RADIATION_BOOTS_DYE.tag, - CNItemTags.ANTI_RADIATION_ARMOR.tag, - CNItemTags.ALL_ANTI_RADIATION_ARMORS.tag + CNTags.CNItemTags.ANTI_RADIATION_ARMOR.tag ) - .lang("Anti Radiation Boots") - .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.COMBAT, c.get()) + .transform(setColorComponent(Cloths.DEFAULT)) + .transform(CNArmorMaterials.setArmorDurability(Type.BOOTS)) + .recipe((c, p) -> { + ShapedRecipeBuilder.shaped(RecipeCategory.COMBAT, c.get()) .unlockedBy("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) .define('X', CNTags.forgeItemTag("ingots/lead")) - .define('Y', ClothItem.Cloths.WHITE_CLOTH.getItem()) + .define('Y', CNTags.forgeItemTag("ingots/brass")) .pattern("Y Y") .pattern("X X") .showNotification(true) - .save(p, CreateNuclear.asResource("crafting/items/armors/" + c.getName()))) - .properties(p -> p.durability(CNArmorMaterials.durabilityForType(ArmorItem.Type.BOOTS))) - .model((c, p) -> p.generated(c, CreateNuclear.asResource("item/armors/anti_radiation_boots"))) + .save(p, CreateNuclear.asResource("crafting/items/armors/" + c.getName())); + + for (Cloths cloth : Cloths.values()) { + if (cloth == Cloths.DEFAULT) continue; + + SmithingClothRecipeBuilder + .smithingCloth( + Ingredient.EMPTY, + Ingredient.of(c.get()), + Ingredient.of(cloth.getItem()), + RecipeCategory.COMBAT, + new ItemStack(c.get()) + ) + .unlocks("has_cloth", RegistrateRecipeProvider.has(CNItemTags.CLOTH.tag)) + .save(p, CreateNuclear.asResource("smithing/" + c.getName() + "_" + cloth.getSerializedName())); + } + }) + .lang("Anti Radiation Boots") + .model(coloredArmorModel("boots", "14")) .register(); - public static final DyeItemList CLOTHS = new ClothItem.DyeItemList<>(color -> { + public static final DyedItemsList CLOTHS = new DyedItemsList<>(color -> { String colorName = color.getSerializedName(); List ingredients = new ArrayList<>(Arrays.asList(Items.WHITE_DYE, Items.ORANGE_DYE, Items.MAGENTA_DYE, Items.LIGHT_BLUE_DYE, Items.YELLOW_DYE, Items.LIME_DYE, Items.PINK_DYE, Items.GRAY_DYE, Items.LIGHT_GRAY_DYE, Items.CYAN_DYE, Items.PURPLE_DYE, Items.BLUE_DYE, Items.BROWN_DYE, Items.GREEN_DYE, Items.RED_DYE, Items.BLACK_DYE)); return CreateNuclear.REGISTRATE.item(colorName+ "_cloth", p -> new ClothItem(p, color)) .tag(CNItemTags.CLOTH.tag) - .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.BUILDING_BLOCKS, c.get()) - .unlockedBy("has_white_cloth", RegistrateRecipeProvider.has(ClothItem.Cloths.WHITE_CLOTH.getItem())) - .requires(CNItemTags.CLOTH.tag) - .requires(ingredients.get(color.ordinal())) - .save(p, CreateNuclear.asResource("shapeless/cloth/" + c.getName())) - ) + .recipe((c, p) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.BUILDING_BLOCKS, c.get()) + .unlockedBy("has_white_cloth", RegistrateRecipeProvider.has(ClothItem.Cloths.WHITE_CLOTH.getItem())) + .requires(Ingredient.of(Arrays.stream(DyeColor.values()) + .filter(o -> o != color) + .map(o -> ClothItem.Cloths.getByColor(o).get()) + .toArray(ClothItem[]::new) + )) + .requires(ingredients.get(color.ordinal())) + .save(p, CreateNuclear.asResource("shapeless/cloth/" + c.getName())) + ) .lang(TextUtils.titleCaseConversion(color.getName()) + " Cloth") .model((c, p) -> p.generated(c, CreateNuclear.asResource("item/cloth/" + colorName + "_cloth"))) .register(); }); - public static final ItemEntry SPAWN_WOLF = registerSpawnEgg("wolf_irradiated_spawn_egg", CNEntityType.IRRADIATED_WOLF, 0x42452B,0x4C422B, "Irradiated Wolf Spawn Egg"); - public static final ItemEntry SPAWN_CAT = registerSpawnEgg("cat_irradiated_spawn_egg", CNEntityType.IRRADIATED_CAT, 0x382C19, 0x742728, "Irradiated Cat Spawn Egg"); - public static final ItemEntry SPAWN_CHICKEN = registerSpawnEgg("chicken_irradiated_spawn_egg", CNEntityType.IRRADIATED_CHICKEN, 0x6B9455, 0x95393C, "Irradiated Chicken Spawn Egg"); + public static final ItemEntry SPAWN_WOLF = CNBuilderTransformers.spawnEgg("wolf_irradiated_spawn_egg", CNEntityType.IRRADIATED_WOLF, 0x42452B, 0x4C422B, "Irradiated Wolf Spawn Egg"); + public static final ItemEntry SPAWN_CAT = CNBuilderTransformers.spawnEgg("cat_irradiated_spawn_egg", CNEntityType.IRRADIATED_CAT, 0x382C19, 0x742728, "Irradiated Cat Spawn Egg"); + public static final ItemEntry SPAWN_CHICKEN = CNBuilderTransformers.spawnEgg("chicken_irradiated_spawn_egg", CNEntityType.IRRADIATED_CHICKEN, 0x6B9455, 0x95393C, "Irradiated Chicken Spawn Egg"); public static final ItemEntry REACTOR_BLUEPRINT = CreateNuclear.REGISTRATE .item("reactor_blueprint_item", ReactorBluePrintItem::new) @@ -292,15 +426,32 @@ public class CNItems { .properties(p -> p.stacksTo(1)) .register(); + public static final ItemEntry REINFORCED_GLASS_BOTTLE = CreateNuclear.REGISTRATE + .item("reinforced_glass_bottle", Item::new) + .lang("Reinforced Glass Bottle") + .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.BREWING, c.get(), 3) + .unlockedBy("has_reinforced_glass", RegistrateRecipeProvider.has(CNBlocks.REINFORCED_GLASS.get())) + .define('G', CNBlocks.REINFORCED_GLASS) + .pattern("G G") + .pattern(" G ") + .save(p, CreateNuclear.asResource("crafting/" + c.getName()))) + .properties(p -> p.stacksTo(16)) + .register(); - private static ItemEntry registerSpawnEgg(String name, Supplier> entity, int backgroundColor, int highlightColor, String nameItems) { - return CreateNuclear.REGISTRATE - .item(name, p -> new DeferredSpawnEggItem(entity, backgroundColor, highlightColor, p)) - .lang(nameItems) - .model((c, p) -> p.withExistingParent(c.getName(), ResourceLocation.withDefaultNamespace("item/template_spawn_egg"))) - .register(); - - } + public static final ItemEntry IRRADIATION_BIOME_EXTRACTOR = CreateNuclear.REGISTRATE + .item("biome_irradiation_extractor", BiomeIrradiationExtractorItem::new) + .lang("Biome Irradiation Extractor") + .recipe((c, p) -> ShapedRecipeBuilder.shaped(RecipeCategory.MISC, c.get(), 8) + .unlockedBy("has_reinforced_glass_bottle", RegistrateRecipeProvider.has(CNItems.REINFORCED_GLASS_BOTTLE.get())) + .define('B', CNItems.REINFORCED_GLASS_BOTTLE) + .define('S', Items.NETHER_STAR) + .pattern("BBB") + .pattern("BSB") + .pattern("BBB") + .save(p, CreateNuclear.asResource("crafting/" + c.getName()))) + .properties(p -> p.stacksTo(16).fireResistant().setNoRepair()) + .model(biomeRestoreModel()) + .register(); public static void register() {} } diff --git a/src/main/java/net/nuclearteam/createnuclear/CNMenus.java b/src/main/java/net/nuclearteam/createnuclear/CNMenus.java index 29d2993..ff58565 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNMenus.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNMenus.java @@ -9,12 +9,12 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintItemScreen; import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintMenu; -import net.nuclearteam.createnuclear.content.multiblock.input.ReactorInputMenu; -import net.nuclearteam.createnuclear.content.multiblock.input.ReactorInputScreen; +import net.nuclearteam.createnuclear.content.multiblock.input.item.ReactorRodInputMenu; +import net.nuclearteam.createnuclear.content.multiblock.input.item.ReactorRodInputScreen; public class CNMenus { public static final MenuEntry REACTOR_BLUEPRINT_MENU = menu("reactor_blueprint_menu", ReactorBluePrintMenu::new, () -> ReactorBluePrintItemScreen::new); - public static final MenuEntry SLOT_ITEM_STORAGE = menu("slot_item_menu", ReactorInputMenu::new, () -> ReactorInputScreen::new); + public static final MenuEntry SLOT_ITEM_STORAGE = menu("slot_item_menu", ReactorRodInputMenu::new, () -> ReactorRodInputScreen::new); private static > MenuEntry menu(String name, ForgeMenuFactory factory, NonNullSupplier> screenFactory) { return CreateNuclear.REGISTRATE diff --git a/src/main/java/net/nuclearteam/createnuclear/CNOpenPipeEffectHandlers.java b/src/main/java/net/nuclearteam/createnuclear/CNOpenPipeEffectHandlers.java new file mode 100644 index 0000000..225109a --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/CNOpenPipeEffectHandlers.java @@ -0,0 +1,10 @@ +package net.nuclearteam.createnuclear; + +import com.simibubi.create.api.effect.OpenPipeEffectHandler; +import net.nuclearteam.createnuclear.content.radiation.RadiationEffectHandler; + +public class CNOpenPipeEffectHandlers { + public static void registerDefaults() { + OpenPipeEffectHandler.REGISTRY.register(CNFluids.URANIUM.getSource(), new RadiationEffectHandler()); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/CNPackets.java b/src/main/java/net/nuclearteam/createnuclear/CNPackets.java index 7543248..257c65e 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNPackets.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNPackets.java @@ -6,16 +6,9 @@ import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintItemPacket; -import net.nuclearteam.createnuclear.content.multiblock.controller.EventTriggerPacket; - import java.util.Locale; public enum CNPackets implements BasePacketPayload.PacketTypeProvider { - CONFIGURE_REACTOR_PATTERN(ReactorBluePrintItemPacket.class, ReactorBluePrintItemPacket.STREAM_CODEC), - - // To client - TRIGGER_EVENT_TEXT_OVERLAY(EventTriggerPacket.class, EventTriggerPacket.STREAM_CODEC), ; private final CatnipPacketRegistry.PacketType type; diff --git a/src/main/java/net/nuclearteam/createnuclear/CNParticleRegistry.java b/src/main/java/net/nuclearteam/createnuclear/CNParticleRegistry.java new file mode 100644 index 0000000..20f7c18 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/CNParticleRegistry.java @@ -0,0 +1,26 @@ +package net.nuclearteam.createnuclear; + +import com.mojang.serialization.Codec; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.core.particles.SimpleParticleType; +import net.neoforged.neoforge.registries.DeferredRegister; +import net.minecraft.core.registries.BuiltInRegistries; +import net.neoforged.neoforge.registries.DeferredHolder; + +public class CNParticleRegistry { + public static final DeferredRegister> DEF_REG; + + public static final DeferredHolder, SimpleParticleType> NUCLEAR_MUSHROOM_CLOUD; + public static final DeferredHolder, SimpleParticleType> NUCLEAR_MUSHROOM_CLOUD_SMOKE; + public static final DeferredHolder, SimpleParticleType> NUCLEAR_MUSHROOM_CLOUD_EXPLOSION; + + static { + DEF_REG = DeferredRegister.create(BuiltInRegistries.PARTICLE_TYPE, CreateNuclear.MOD_ID); + NUCLEAR_MUSHROOM_CLOUD = DEF_REG.register("nuclear_mushroom_cloud", () -> new SimpleParticleType(false)); + NUCLEAR_MUSHROOM_CLOUD_SMOKE = DEF_REG.register("nuclear_mushroom_cloud_smoke", () -> new SimpleParticleType(false)); + NUCLEAR_MUSHROOM_CLOUD_EXPLOSION = DEF_REG.register("nuclear_mushroom_cloud_explosion", () -> new SimpleParticleType(false)); + } + +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/CNParticleTypes.java b/src/main/java/net/nuclearteam/createnuclear/CNParticleTypes.java new file mode 100644 index 0000000..28983f1 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/CNParticleTypes.java @@ -0,0 +1,69 @@ +package net.nuclearteam.createnuclear; + +import com.simibubi.create.foundation.particle.ICustomParticleData; +import net.createmod.catnip.lang.Lang; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent; +import net.neoforged.neoforge.registries.DeferredRegister; +import net.minecraft.core.registries.BuiltInRegistries; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.bus.api.IEventBus; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.nuclearteam.createnuclear.content.particles.IrradiatedParticlesData; + +import java.util.function.Supplier; + +public enum CNParticleTypes { + + IRRADIATED_PARTICLES(IrradiatedParticlesData::new), + ; + + private final ParticleEntry entry; + + CNParticleTypes(Supplier> typeFactory) { + String name = Lang.asId(name()); + entry = new ParticleEntry<>(name, typeFactory); + } + + public static void register(IEventBus modEventBus) { + ParticleEntry.REGISTER.register(modEventBus); + } + + @OnlyIn(Dist.CLIENT) + public static void registerFactories(RegisterParticleProvidersEvent event) { + for (CNParticleTypes particle : values()) + particle.entry.registerFactory(event); + } + + public ParticleType get() { + return entry.object.get(); + } + + public String parameter() { + return entry.name; + } + + + private static class ParticleEntry { + private static final DeferredRegister> REGISTER = DeferredRegister.create(BuiltInRegistries.PARTICLE_TYPE, CreateNuclear.MOD_ID); + + private final String name; + private final Supplier> typeFactory; + private final DeferredHolder, ParticleType> object; + + public ParticleEntry(String name, Supplier> typeFactory) { + this.name = name; + this.typeFactory = typeFactory; + + object = REGISTER.register(name, () -> this.typeFactory.get().createType()); + } + + @OnlyIn(Dist.CLIENT) + public void registerFactory(RegisterParticleProvidersEvent event) { + typeFactory.get() + .register(object.get(), event); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/CNPotions.java b/src/main/java/net/nuclearteam/createnuclear/CNPotions.java index 98b0ae3..643b20e 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNPotions.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNPotions.java @@ -23,6 +23,13 @@ public class CNPotions { public static final Holder POTION_2 = CN_POTIONS.register("potion_of_radiation_2", () -> new Potion(new MobEffectInstance(CNEffects.RADIATION.getDelegate(), 410, 1))); + public static final Holder POTION_1_IODINE = CN_POTIONS.register("potion_of_iodine", + () -> new Potion(new MobEffectInstance(CNEffects.IODINE.getDelegate(), 900)) + ); + public static final Holder POTION_AUGMENT_1_IODINE = CN_POTIONS.register("potion_of_iodine_augment", + () -> new Potion(new MobEffectInstance(CNEffects.IODINE.getDelegate(), 1800)) + ); + public static void register(IEventBus eventBus) { CN_POTIONS.register(eventBus); } @@ -33,5 +40,8 @@ public static void registerPotionsRecipes(RegisterBrewingRecipesEvent event) { builder.addMix(Potions.AWKWARD, CNItems.ENRICHED_YELLOWCAKE.get(), POTION_1); builder.addMix(POTION_1, Items.REDSTONE, POTION_AUGMENT_1); builder.addMix(POTION_1, Items.GLOWSTONE_DUST, POTION_2); + + builder.addMix(Potions.AWKWARD, Items.DRIED_KELP, POTION_1_IODINE); + builder.addMix(POTION_1_IODINE, Items.REDSTONE, POTION_AUGMENT_1_IODINE); } } diff --git a/src/main/java/net/nuclearteam/createnuclear/CNRecipeTypes.java b/src/main/java/net/nuclearteam/createnuclear/CNRecipeTypes.java index 2b79d3d..b15e2d2 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNRecipeTypes.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNRecipeTypes.java @@ -16,6 +16,7 @@ import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; import net.nuclearteam.createnuclear.content.kinetics.fan.processing.EnrichedRecipe; +import net.nuclearteam.createnuclear.content.kinetics.fan.processing.SnowPowderRecipe; import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,7 +27,8 @@ @SuppressWarnings({"unused", "unchecked"}) public enum CNRecipeTypes implements IRecipeTypeInfo, StringRepresentable { - ENRICHED(EnrichedRecipe::new) + ENRICHED(EnrichedRecipe::new), + SNOW_POWDER(SnowPowderRecipe::new) ; public static final Predicate> CAN_BE_AUTOMATED = r -> !r.id() diff --git a/src/main/java/net/nuclearteam/createnuclear/CNShapes.java b/src/main/java/net/nuclearteam/createnuclear/CNShapes.java index b32f6d2..9e30709 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNShapes.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNShapes.java @@ -12,11 +12,11 @@ @SuppressWarnings("unused") public class CNShapes { - // Independent Shapers public static final VoxelShaper - REACTOR_OUTPUT = shape(0, 0, 0, 16, 14, 16).forDirectional(), - REACTOR_INPUT = shape(0,0,0,16,16,16).forDirectional() + REACTOR_OUTPUT = shape(0, 0, 0, 16, 14, 16).forDirectional(), + REACTOR_INPUT = shape(0,0,0,16,16,16).forDirectional(), + REACTOR_FLUID_INPUT = shape(0,0,0,16,16,16).forDirectional() ; private static Builder shape(VoxelShape shape) { diff --git a/src/main/java/net/nuclearteam/createnuclear/CNSoundEvents.java b/src/main/java/net/nuclearteam/createnuclear/CNSoundEvents.java new file mode 100644 index 0000000..5ce274e --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/CNSoundEvents.java @@ -0,0 +1,434 @@ +package net.nuclearteam.createnuclear; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.AllSoundEvents.ConfiguredSoundEvent; +import com.simibubi.create.AllSoundEvents.SoundEntry; +import com.simibubi.create.Create; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.CachedOutput; +import net.minecraft.data.DataGenerator; +import net.minecraft.data.DataProvider; +import net.minecraft.data.PackOutput; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.RegisterEvent; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +public class CNSoundEvents { + + public static final Map ALL = new HashMap<>(); + + public static final SoundEntry + + REACTOR_ACTIVATION = create("reacteur/activation") + .subtitle("Reactor Activation") + .category(SoundSource.BLOCKS) + .build(), + + REACTOR_RUNNING = create("reacteur/running") + .subtitle("Reactor Running") + .category(SoundSource.BLOCKS) + .build(), + + REACTOR_SHUT_OFF = create("reacteur/shut_off") + .subtitle("Reactor Shut Off") + .category(SoundSource.BLOCKS) + .build(), + + REACTOR_ALARM_ONESHOT = create("alarm/reactor", "alarm") + .subtitle("Reactor Alarm") + .category(SoundSource.BLOCKS) + .build(), + + REACTOR_ALARM_LOOP = create("alarm/alarm") + .subtitle("Reactor Alarm Loop") + .category(SoundSource.BLOCKS) + .build(), + + NUCLEAR_EXPLOSION = create("explosion/nuclear_explosion") + .subtitle("Nuclear Explosion") + .category(SoundSource.AMBIENT) + .build(), + + NUCLEAR_EXPLOSION_LARGE = create("explosion/large_nuclear_explosion") + .subtitle("Large Nuclear Explosion") + .category(SoundSource.AMBIENT) + .build(), + + NUCLEAR_EXPLOSION_RINGING = create("explosion/ringing") + .subtitle("Nuclear Explosion Ringing") + .category(SoundSource.AMBIENT) + .build(), + + NUCLEAR_EXPLOSION_RUMBLE = create("explosion/nuclear_explosion_rumble") + .subtitle("Nuclear Explosion Rumble") + .category(SoundSource.AMBIENT) + .build(), + + MOTOR_ASSEMBLE = create("reacteur/assemble_deassemble/motor_assemble") + .subtitle("Motor Assemble") + .category(SoundSource.BLOCKS) + .build(), + + MOTOR_DISASSEMBLE = create("reacteur/assemble_deassemble/motor_disassemble") + .subtitle("Motor Disassemble") + .category(SoundSource.BLOCKS) + .build(), + + NUCLEAR_EXPLOSION_RUMBLE_2 = create("explosion/rumble") + .subtitle("Nuclear Explosion Rumble") + .category(SoundSource.AMBIENT) + .build(), + + NUCLEAR_EXPLOSION_MAIN = create("explosion/main") + .subtitle("Nuclear Explosion Main") + .category(SoundSource.AMBIENT) + .build(), + + NUCLEAR_EXPLOSION_SHOCKWAVE = create("explosion/shockwave") + .subtitle("Nuclear Explosion Shockwave") + .category(SoundSource.AMBIENT) + .build(), + + GEIGER_HIGH = create("geiger/high") + .subtitle("Geiger High") + .category(SoundSource.AMBIENT) + .build(), + + GEIGER_LOW = create("geiger/low") + .subtitle("Geiger Low") + .category(SoundSource.AMBIENT) + .build(), + + GEIGER_MEDIUM = create("geiger/medium") + .subtitle("Geiger Medium") + .category(SoundSource.AMBIENT) + .build(), + + BIOME_WASTELAND = create("biomes/wasteland") + .subtitle("Wasteland") + .category(SoundSource.AMBIENT) + .build() + ; + + private static SoundEntryBuilder create(String... pathParts) { + String name = String.join("_", pathParts); + return create(CreateNuclear.asResource(name)); + } + + private static SoundEntryBuilder create(ResourceLocation id) { + return new SoundEntryBuilder(id); + } + + public static void prepare() { + for (SoundEntry entry : ALL.values()) entry.prepare(); + } + + public static void register(RegisterEvent event) { + event.register(Registries.SOUND_EVENT, helper -> { + for (SoundEntry entry : ALL.values()) entry.register(helper); + }); + } + + public static void provideLang(BiConsumer consumer) { + for (SoundEntry entry : ALL.values()) + if (entry.hasSubtitle()) + consumer.accept(entry.getSubtitleKey(), entry.getSubtitle()); + } + + public static SoundEntryProvider provider(DataGenerator generator) { + return new SoundEntryProvider(generator); + } + + public static void playItemPickup(Player player) { + player.level().playSound( + null, + player.blockPosition(), + SoundEvents.ITEM_PICKUP, + SoundSource.PLAYERS, + .2f, + 1f + player.level().random.nextFloat() + ); + } + + public static class SoundEntryProvider implements DataProvider { + + private PackOutput output; + + public SoundEntryProvider(DataGenerator generator) { + output = generator.getPackOutput(); + } + + @Override + public CompletableFuture run(CachedOutput cache) { + return generate(output.getOutputFolder(), cache); + } + + @Override + public String getName() { + return "CreateNuclear's Custom Sounds"; + } + + public CompletableFuture generate(Path path, CachedOutput cache) { + path = path.resolve("assets/createnuclear"); + JsonObject json = new JsonObject(); + ALL.entrySet() + .stream() + .sorted(Map.Entry.comparingByKey()) + .forEach(entry -> { + entry.getValue() + .write(json); + }); + return DataProvider.saveStable(cache, json, path.resolve("sounds.json")); + } + + } + + public static class SoundEntryBuilder { + + protected ResourceLocation id; + protected String subtitle = "unregistered"; + protected SoundSource category = SoundSource.BLOCKS; + protected List wrappedEvents; + protected List variants; + protected int attenuationDistance; + + public SoundEntryBuilder(ResourceLocation id) { + wrappedEvents = new ArrayList<>(); + variants = new ArrayList<>(); + this.id = id; + } + + public SoundEntryBuilder subtitle(String subtitle) { + this.subtitle = subtitle; + return this; + } + + public SoundEntryBuilder attenuationDistance(int distance) { + this.attenuationDistance = distance; + return this; + } + + public SoundEntryBuilder noSubtitle() { + this.subtitle = null; + return this; + } + + public SoundEntryBuilder category(SoundSource category) { + this.category = category; + return this; + } + + public SoundEntryBuilder addVariant(String name) { + return addVariant(Create.asResource(name)); + } + + public SoundEntryBuilder addVariant(ResourceLocation id) { + variants.add(id); + return this; + } + + public SoundEntryBuilder playExisting(Supplier event, float volume, float pitch) { + wrappedEvents.add(new ConfiguredSoundEvent(event, volume, pitch)); + return this; + } + + public SoundEntryBuilder playExisting(SoundEvent event, float volume, float pitch) { + return playExisting(() -> event, volume, pitch); + } + + public SoundEntryBuilder playExisting(SoundEvent event) { + return playExisting(event, 1, 1); + } + + public SoundEntryBuilder playExisting(Holder event) { + return playExisting(event::value, 1, 1); + } + + public SoundEntry build() { + SoundEntry entry = + wrappedEvents.isEmpty() ? new CustomSoundEntry(id, variants, subtitle, category, attenuationDistance) + : new WrappedSoundEntry(id, subtitle, wrappedEvents, category, attenuationDistance); + ALL.put(entry.getId(), entry); + return entry; + } + + } + + private static class CustomSoundEntry extends SoundEntry { + + protected List variants; + protected DeferredHolder event; + + public CustomSoundEntry(ResourceLocation id, List variants, String subtitle, + SoundSource category, int attenuationDistance) { + super(id, subtitle, category, attenuationDistance); + this.variants = variants; + } + + @Override + public void prepare() { + event = DeferredHolder.create(Registries.SOUND_EVENT, id); + } + + @Override + public void register(RegisterEvent.RegisterHelper helper) { + ResourceLocation location = event.getId(); + helper.register(location, SoundEvent.createVariableRangeEvent(location)); + } + + @Override + public Holder getMainEventHolder() { + return event; + } + + @Override + public SoundEvent getMainEvent() { + return event.get(); + } + + @Override + public void write(JsonObject json) { + JsonObject entry = new JsonObject(); + JsonArray list = new JsonArray(); + + JsonObject s = new JsonObject(); + s.addProperty("name", id.toString()); + s.addProperty("type", "file"); + if (attenuationDistance != 0) + s.addProperty("attenuation_distance", attenuationDistance); + list.add(s); + + for (ResourceLocation variant : variants) { + s = new JsonObject(); + s.addProperty("name", variant.toString()); + s.addProperty("type", "file"); + if (attenuationDistance != 0) + s.addProperty("attenuation_distance", attenuationDistance); + list.add(s); + } + + entry.add("sounds", list); + if (hasSubtitle()) + entry.addProperty("subtitle", getSubtitleKey()); + json.add(id.getPath(), entry); + } + + @Override + public void play(Level world, Player entity, double x, double y, double z, float volume, float pitch) { + world.playSound(entity, x, y, z, event.get(), category, volume, pitch); + } + + @Override + public void playAt(Level world, double x, double y, double z, float volume, float pitch, boolean fade) { + world.playLocalSound(x, y, z, event.get(), category, volume, pitch, fade); + } + + } + + private static class WrappedSoundEntry extends SoundEntry { + + private List wrappedEvents; + private List compiledEvents; + + public WrappedSoundEntry(ResourceLocation id, String subtitle, + List wrappedEvents, SoundSource category, int attenuationDistance) { + super(id, subtitle, category, attenuationDistance); + this.wrappedEvents = wrappedEvents; + compiledEvents = new ArrayList<>(); + } + + @Override + public void prepare() { + for (int i = 0; i < wrappedEvents.size(); i++) { + ConfiguredSoundEvent wrapped = wrappedEvents.get(i); + ResourceLocation location = getIdOf(i); + DeferredHolder event = DeferredHolder.create(Registries.SOUND_EVENT, location); + compiledEvents.add(new CompiledSoundEvent(event, wrapped.volume(), wrapped.pitch())); + } + } + + @Override + public void register(RegisterEvent.RegisterHelper helper) { + for (CompiledSoundEvent compiledEvent : compiledEvents) { + ResourceLocation location = compiledEvent.event().getId(); + helper.register(location, SoundEvent.createVariableRangeEvent(location)); + } + } + + @Override + public Holder getMainEventHolder() { + return compiledEvents.getFirst().event(); + } + + @Override + public SoundEvent getMainEvent() { + return compiledEvents.get(0) + .event().get(); + } + + protected ResourceLocation getIdOf(int i) { + return ResourceLocation.fromNamespaceAndPath(id.getNamespace(), i == 0 ? id.getPath() : id.getPath() + "_compounded_" + i); + } + + @Override + public void write(JsonObject json) { + for (int i = 0; i < wrappedEvents.size(); i++) { + ConfiguredSoundEvent event = wrappedEvents.get(i); + JsonObject entry = new JsonObject(); + JsonArray list = new JsonArray(); + JsonObject s = new JsonObject(); + s.addProperty("name", event.event() + .get() + .getLocation() + .toString()); + s.addProperty("type", "event"); + if (attenuationDistance != 0) + s.addProperty("attenuation_distance", attenuationDistance); + list.add(s); + entry.add("sounds", list); + if (i == 0 && hasSubtitle()) + entry.addProperty("subtitle", getSubtitleKey()); + json.add(getIdOf(i).getPath(), entry); + } + } + + @Override + public void play(Level world, Player entity, double x, double y, double z, float volume, float pitch) { + for (WrappedSoundEntry.CompiledSoundEvent event : compiledEvents) { + world.playSound(entity, x, y, z, event.event().get(), category, event.volume() * volume, + event.pitch() * pitch); + } + } + + @Override + public void playAt(Level world, double x, double y, double z, float volume, float pitch, boolean fade) { + for (WrappedSoundEntry.CompiledSoundEvent event : compiledEvents) { + world.playLocalSound(x, y, z, event.event().get(), category, event.volume() * volume, + event.pitch() * pitch, fade); + } + } + + private record CompiledSoundEvent(DeferredHolder event, float volume, float pitch) { + } + + } + +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/CNTags.java b/src/main/java/net/nuclearteam/createnuclear/CNTags.java index 5582652..2d54f4f 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CNTags.java +++ b/src/main/java/net/nuclearteam/createnuclear/CNTags.java @@ -71,10 +71,8 @@ public enum NameSpace { public enum CNBlockTags { FAN_PROCESSING_CATALYSTS_ENRICHED(MOD, "fan_processing_catalysts/enriched"), + FAN_PROCESSING_CATALYSTS_SNOW_POWDER(MOD, "fan_processing_catalysts/snow_powder"), ENRICHING_FIRE_BASE_BLOCKS, - ALL_CAMPFIRES(MINECRAFT, "all/campfires"), - URANIUM_ORES, - LEAD_ORES ; public final TagKey tag; @@ -125,17 +123,9 @@ public enum CNItemTags { CLOTH, FUEL, COOLER, - URANIUM_ORES, - LEAD_ORES, - ANTI_RADIATION_HELMET_DYE, - ANTI_RADIATION_CHESTPLATE_DYE, - ANTI_RADIATION_LEGGINGS_DYE, - ANTI_RADIATION_BOOTS_DYE, ANTI_RADIATION_ARMOR, - ALL_ANTI_RADIATION_ARMORS, - ANTI_RADIATION_HELMET_FULL_DYE, - ANTI_RADIATION_CHESTPLATE_FULL_DYE, - ANTI_RADIATION_LEGGINGS_FULL_DYE, + ANTI_RADIATION_HELMET, + THORIUM_ORES, ; public final TagKey tag; @@ -179,7 +169,9 @@ private static void init() {} } public enum CNFluidTags { - URANIUM + URANIUM, + THORIUM, + NITROGEN ; public final TagKey tag; diff --git a/src/main/java/net/nuclearteam/createnuclear/CreateNuclear.java b/src/main/java/net/nuclearteam/createnuclear/CreateNuclear.java index cf33877..d2b1608 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CreateNuclear.java +++ b/src/main/java/net/nuclearteam/createnuclear/CreateNuclear.java @@ -2,19 +2,20 @@ import com.mojang.logging.LogUtils; -import com.simibubi.create.AllDataComponents; import com.simibubi.create.CreateBuildInfo; +import com.simibubi.create.content.equipment.goggles.GogglesItem; import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.item.KineticStats; +import net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem; +import net.nuclearteam.createnuclear.foundation.item.RodsStats; import com.simibubi.create.foundation.item.TooltipModifier; -import com.simibubi.create.infrastructure.data.CreateDatagen; import net.createmod.catnip.lang.FontHelper; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.CreativeModeTab; -import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.ModContainer; @@ -23,13 +24,17 @@ import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.registries.RegisterEvent; +import net.nuclearteam.createnuclear.content.contraptions.irradiated.IrradiatedAnimal; import net.nuclearteam.createnuclear.content.decoration.palettes.CNPaletteBlocks; import net.nuclearteam.createnuclear.content.equipment.armor.CNArmorMaterials; import net.nuclearteam.createnuclear.content.kinetics.fan.processing.CNFanProcessingTypes; +import net.nuclearteam.createnuclear.content.radiation.CNRadiationValues; import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancement; import net.nuclearteam.createnuclear.foundation.advancement.CNTriggers; import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; import net.nuclearteam.createnuclear.infrastructure.data.CreateNuclearDatagen; +import net.nuclearteam.createnuclear.infrastructure.worldgen.CNPlacementModifiers; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.surfacerule.BiomeTagRule; import org.slf4j.Logger; import com.simibubi.create.api.registrate.CreateRegistrateRegistrationCallback; @@ -50,6 +55,7 @@ public class CreateNuclear { .setTooltipModifierFactory(item -> new ItemDescription.Modifier(item, FontHelper.Palette.STANDARD_CREATE) .andThen(TooltipModifier.mapNull(KineticStats.create(item))) + .andThen(RodsStats.create(item)) ); public CreateNuclear(IEventBus eventBus, ModContainer modContainer) { @@ -65,7 +71,8 @@ public static void onCtor(IEventBus modEventBus, ModContainer modContainer) { REGISTRATE.registerEventListeners(modEventBus); - + CNSoundEvents.prepare(); + CNDisplaySources.register(); CNTags.init(); CNBlocks.register(); CNBlockEntityTypes.register(); @@ -78,13 +85,20 @@ public static void onCtor(IEventBus modEventBus, ModContainer modContainer) { CNArmorMaterials.register(modEventBus); CNDataComponents.register(modEventBus); + CNAttachmentTypes.register(modEventBus); CNConfigs.register(modLoadingContext, modContainer); CNCreativeModeTabs.register(modEventBus); CNEffects.register(modEventBus); CNPotions.register(modEventBus); + CNParticleTypes.register(modEventBus); + CNParticleRegistry.DEF_REG.register(modEventBus); CNRecipeTypes.register(modEventBus); + CNAttributes.register(modEventBus); + CNPlacementModifiers.register(modEventBus); + + GogglesItem.addIsWearingPredicate(AntiRadiationArmorItem.IGoggleHelmet::isGoggleHelmet); modEventBus.addListener(CreateNuclear::init); modEventBus.addListener(CreateNuclear::onRegister); @@ -98,10 +112,16 @@ public static void onCtor(IEventBus modEventBus, ModContainer modContainer) { public static void init(final FMLCommonSetupEvent event) { CNFluids.registerFluidInteractions(); + CNRadiationValues.register(); + + event.enqueueWork(CNOpenPipeEffectHandlers::registerDefaults); + event.enqueueWork(() -> IrradiatedAnimal.VANILLA_TO_IRRADIATED.put(EntityType.CHICKEN, CNEntityType.IRRADIATED_CHICKEN.get())); } public static void onRegister(final RegisterEvent event) { + CNSoundEvents.register(event); CNFanProcessingTypes.register(); + BiomeTagRule.register(event); if (event.getRegistry() == BuiltInRegistries.TRIGGER_TYPES) { CNAdvancement.register(); diff --git a/src/main/java/net/nuclearteam/createnuclear/CreateNuclearClient.java b/src/main/java/net/nuclearteam/createnuclear/CreateNuclearClient.java index a556d60..b8de154 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CreateNuclearClient.java +++ b/src/main/java/net/nuclearteam/createnuclear/CreateNuclearClient.java @@ -20,11 +20,9 @@ public static void onCtorClient(IEventBus modEventBus) { IEventBus neoEventBus = NeoForge.EVENT_BUS; modEventBus.addListener(CreateNuclearClient::clientInit); - } public static void clientInit(final FMLClientSetupEvent event) { PonderIndex.addPlugin(new CreateNuclearPonderPlugin()); - } } diff --git a/src/main/java/net/nuclearteam/createnuclear/api/CreateNuclearRegistries.java b/src/main/java/net/nuclearteam/createnuclear/api/CreateNuclearRegistries.java new file mode 100644 index 0000000..c1c8c61 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/api/CreateNuclearRegistries.java @@ -0,0 +1,19 @@ +package net.nuclearteam.createnuclear.api; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.multiblock.fluid.ReactorFluidType; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; + +public class CreateNuclearRegistries { + public static final ResourceKey> ROD_TYPE = key("rods/type"); + public static final ResourceKey> FLUID_TYPE = key("fluids/type"); + + public static final ResourceKey FALLBACK_ROD = ResourceKey.create(CreateNuclearRegistries.ROD_TYPE, CreateNuclear.asResource("fallback")); + public static final ResourceKey FALLBACK_FLUID = ResourceKey.create(CreateNuclearRegistries.FLUID_TYPE, CreateNuclear.asResource("fallback")); + + private static ResourceKey> key(String name) { + return ResourceKey.createRegistryKey(CreateNuclear.asResource(name)); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/api/ItemRodTypesValue.java b/src/main/java/net/nuclearteam/createnuclear/api/ItemRodTypesValue.java new file mode 100644 index 0000000..e617392 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/api/ItemRodTypesValue.java @@ -0,0 +1,79 @@ +package net.nuclearteam.createnuclear.api; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.tterrag.registrate.util.nullness.NonNullConsumer; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; +import static net.nuclearteam.createnuclear.api.multiblock.rods.RodType.TypeRod.NONE; + +import java.util.Collections; + +import net.minecraft.core.HolderSet; + +public class ItemRodTypesValue { + public static final SimpleRegistry ROD_TYPE = SimpleRegistry.create(); + /** + * Default RodType returned when no mapping exists in the registry. + * Built once to avoid allocating a new instance on each lookup. + */ + public static final RodType DEFAULT_ROD_TYPE = new RodType(Items.AIR.builtInRegistryHolder(), -1, -1, -1, NONE); + + /** + * Get the {@link RodType} associated with the given {@link Item}. + * If no mapping exists, a default empty {@link RodType} is returned. + * + * @param item the item to look up (must not be null) + * @return the associated {@link RodType} or a default instance if none present + * @throws NullPointerException if {@code item} is null + */ + public static RodType getRodType(Item item) { + RodType type = ROD_TYPE.get(item); + return type == null ? DEFAULT_ROD_TYPE : type; + } + + /** + * Create a consumer that registers the given {@link RodType} for an item. + * + * @param type the rod type to register (must not be null) + * @return a non-null consumer that registers the mapping + * @throws NullPointerException if {@code type} is null + */ + public static NonNullConsumer setRodTypeInfos(RodType.Builder type) { + return item -> ROD_TYPE.register(item, type.item(item).build()); + } + + + /** + * Create a consumer that builds a {@link RodType} using the provided numeric + * parameters and registers it for the item passed to the consumer. + * + * The {@code type} parameter controls whether the builder configures the + * rod as a cooler, fuel or keeps the default mixed behaviour. For MIXTE + * we keep the builder default and do not call any explicit setter. + * + * @param baseRodHeat base heat value + * @param proximityRodHeat heat influenced by proximity + * @param rodTimer rod life / timer value + * @param type enum controlling cooler/fuel/mixte behaviour (must not be null) + * @return a non-null consumer that registers the built RodType + * @throws NullPointerException if {@code type} is null + */ + public static NonNullConsumer setRodTypeInfos(int baseRodHeat, int proximityRodHeat, int rodTimer, RodType.TypeRod type) { + RodType.Builder builder = new RodType.Builder() + .baseRodHeat(baseRodHeat) + .proximityRodHeat(proximityRodHeat) + .rodTimer(rodTimer); + + switch (type) { + case COOLER -> builder.coolerRodType(); + case FUEL -> builder.fuelRodType(); + default -> throw new IllegalArgumentException("Unsupported TypeRod: " + type + ". This error occurred during rod stats initialization in the CreateNuclearForge mod."); + } + + return item -> { + RodType built = builder.item(item).build(); + ROD_TYPE.register(item, built); + }; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/api/ReactorFluidTypesValue.java b/src/main/java/net/nuclearteam/createnuclear/api/ReactorFluidTypesValue.java new file mode 100644 index 0000000..d994f80 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/api/ReactorFluidTypesValue.java @@ -0,0 +1,85 @@ +package net.nuclearteam.createnuclear.api; + +import com.simibubi.create.api.registry.SimpleRegistry; +import com.tterrag.registrate.util.nullness.NonNullConsumer; +import net.minecraft.core.HolderSet; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; +import net.nuclearteam.createnuclear.api.multiblock.fluid.ReactorFluidType; + +import java.util.Collections; + +/** + * Registry-backed accessors for {@link ReactorFluidType} mappings. + *

+ * This class provides a simple registry that maps {@link Fluid} instances to + * their corresponding {@link ReactorFluidType} definitions. It also exposes + * helper methods that produce consumers suitable for registering reactor + * fluid type information during mod initialization. + */ +public class ReactorFluidTypesValue { + /** + * Simple in-memory registry mapping fluids to {@link ReactorFluidType}. + */ + public static final SimpleRegistry REACTOR_FLUID_TYPE = SimpleRegistry.create(); + + /** + * Default {@link ReactorFluidType} returned when no mapping exists in the + * registry. Constructed once to avoid allocating a new instance on each lookup. + */ + public static final ReactorFluidType DEFAULT_REACTOR_FLUID_TYPE = new ReactorFluidType(Fluids.EMPTY.builtInRegistryHolder(), -1, -1); + + /** + * Get the {@link ReactorFluidType} associated with the given {@link Fluid}. + * If no mapping exists, a default empty {@link ReactorFluidType} is returned. + * + * @param fluid the fluid to look up (must not be null) + * @return the associated {@link ReactorFluidType} or a default instance if none present + * @throws NullPointerException if {@code fluid} is null + */ + public static ReactorFluidType getReactorFluidType(Fluid fluid) { + ReactorFluidType type = REACTOR_FLUID_TYPE.get(fluid); + return type == null ? DEFAULT_REACTOR_FLUID_TYPE : type; + } + + /** + * Create a consumer that registers the given {@link ReactorFluidType} + * builder for a fluid. + *

+ * The returned consumer will call {@link ReactorFluidType.Builder#fluid(Fluid)} + * with the provided fluid and then build and register the resulting + * {@link ReactorFluidType} into the registry. + * + * @param type the reactor fluid type builder to register (must not be null) + * @return a non-null consumer that registers the mapping + */ + public static NonNullConsumer setReactorFluidTypeInfos(ReactorFluidType.Builder type) { + return fluid -> REACTOR_FLUID_TYPE.register(fluid, type.fluid(fluid).build()); + } + + /** + * Create a consumer that builds a {@link ReactorFluidType} using the + * provided numeric parameters and registers it for the fluid passed to + * the consumer. + *

+ * The returned consumer will construct a builder pre-configured with the + * provided {@code maxHeat} and {@code efficiency} values, then call + * {@link ReactorFluidType.Builder#fluid(Fluid)} and register the built + * instance for the supplied fluid. + * + * @param maxHeat maximum heat value to apply to the built type + * @param efficiency efficiency value to apply to the built type + * @return a non-null consumer that registers the built {@link ReactorFluidType} + */ + public static NonNullConsumer setReactorFluidTypeInfos(int maxHeat, int efficiency) { + ReactorFluidType.Builder builder = new ReactorFluidType.Builder() + .maxHeat(maxHeat) + .efficiency(efficiency); + + return fluid -> { + ReactorFluidType built = builder.fluid(fluid).build(); + REACTOR_FLUID_TYPE.register(fluid, built); + }; + } + +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/EnrichedRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/api/data/recipe/EnrichedRecipeGen.java similarity index 78% rename from src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/EnrichedRecipeGen.java rename to src/main/java/net/nuclearteam/createnuclear/api/data/recipe/EnrichedRecipeGen.java index 8600de4..6b2b031 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/EnrichedRecipeGen.java +++ b/src/main/java/net/nuclearteam/createnuclear/api/data/recipe/EnrichedRecipeGen.java @@ -1,4 +1,4 @@ -package net.nuclearteam.createnuclear.foundation.data.recipe; +package net.nuclearteam.createnuclear.api.data.recipe; import com.simibubi.create.api.data.recipe.ProcessingRecipeGen; import com.simibubi.create.api.data.recipe.StandardProcessingRecipeGen; @@ -18,7 +18,7 @@ * The base class for Haunting recipe generation. * Addons should extend this and use the {@link ProcessingRecipeGen#create} methods * or the helper methods contained in this class to make recipes. - * For an example of how you might do this, see Create's implementation: {@link net.nuclearteam.createnuclear.foundation.data.recipe.CNEnrichedRecipeGen}. + * For an example of how you might do this, see {@link net.nuclearteam.createnuclear.foundation.data.recipe.CNEnrichedRecipeGen}. * Needs to be added to a registered recipe provider to do anything, see {@link net.nuclearteam.createnuclear.foundation.data.recipe.CNRecipeProvider} */ public abstract class EnrichedRecipeGen extends StandardProcessingRecipeGen { @@ -33,12 +33,12 @@ public GeneratedRecipe convert(Supplier input, Supplier re .output(result.get())); } - public EnrichedRecipeGen(PackOutput output, CompletableFuture registries, String defaultNamespace) { - super(output, registries, defaultNamespace); + public EnrichedRecipeGen(PackOutput generator, CompletableFuture registries, String defaultNamespace) { + super(generator, registries, defaultNamespace); } @Override - protected CNRecipeTypes getRecipeType() { + protected IRecipeTypeInfo getRecipeType() { return CNRecipeTypes.ENRICHED; } } diff --git a/src/main/java/net/nuclearteam/createnuclear/api/data/recipe/SmithingClothRecipeBuilder.java b/src/main/java/net/nuclearteam/createnuclear/api/data/recipe/SmithingClothRecipeBuilder.java new file mode 100644 index 0000000..857323b --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/api/data/recipe/SmithingClothRecipeBuilder.java @@ -0,0 +1,59 @@ +package net.nuclearteam.createnuclear.api.data.recipe; + +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementRequirements; +import net.minecraft.advancements.AdvancementRewards; +import net.minecraft.advancements.Criterion; +import net.minecraft.advancements.critereon.RecipeUnlockedTrigger; +import net.minecraft.data.recipes.RecipeCategory; +import net.minecraft.data.recipes.RecipeOutput; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.SmithingTransformRecipe; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class SmithingClothRecipeBuilder { + private final Ingredient template; + private final Ingredient base; + private final Ingredient addition; + private final RecipeCategory category; + private final ItemStack result; + private final Map> criteria = new LinkedHashMap<>(); + + public SmithingClothRecipeBuilder(Ingredient pTemplate, Ingredient pBase, Ingredient pAddition, RecipeCategory pCategory, ItemStack pResult) { + this.category = pCategory; + this.template = pTemplate; + this.base = pBase; + this.addition = pAddition; + this.result = pResult; + } + + public static SmithingClothRecipeBuilder smithingCloth(Ingredient pTemplate, Ingredient pBase, Ingredient pAddition, RecipeCategory pCategory, ItemStack pResult) { + return new SmithingClothRecipeBuilder(pTemplate, pBase, pAddition, pCategory, pResult); + } + + public SmithingClothRecipeBuilder unlocks(String pKey, Criterion pCriterion) { + this.criteria.put(pKey, pCriterion); + return this; + } + + public void save(RecipeOutput pRecipeOutput, ResourceLocation pLocation) { + this.ensureValid(pLocation); + Advancement.Builder advancement = pRecipeOutput.advancement() + .addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(pLocation)) + .rewards(AdvancementRewards.Builder.recipe(pLocation)) + .requirements(AdvancementRequirements.Strategy.OR); + this.criteria.forEach(advancement::addCriterion); + SmithingTransformRecipe recipe = new SmithingTransformRecipe(this.template, this.base, this.addition, this.result); + pRecipeOutput.accept(pLocation, recipe, advancement.build(pLocation.withPrefix("recipes/" + this.category.getFolderName() + "/"))); + } + + private void ensureValid(ResourceLocation pLocation) { + if (this.criteria.isEmpty()) { + throw new IllegalStateException("No way of obtaining recipe " + pLocation); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/api/data/recipe/SnowPowderRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/api/data/recipe/SnowPowderRecipeGen.java new file mode 100644 index 0000000..ee1f66e --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/api/data/recipe/SnowPowderRecipeGen.java @@ -0,0 +1,43 @@ +package net.nuclearteam.createnuclear.api.data.recipe; + +import com.simibubi.create.api.data.recipe.ProcessingRecipeGen; +import com.simibubi.create.api.data.recipe.StandardProcessingRecipeGen; +import net.createmod.catnip.registry.RegisteredObjectsHelper; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.ItemLike; +import net.nuclearteam.createnuclear.CNRecipeTypes; +import net.nuclearteam.createnuclear.content.kinetics.fan.processing.SnowPowderRecipe; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; + +/** + * The base class for Snow Powder recipe generation. + * Addons should extend this and use the {@link ProcessingRecipeGen#create} methods + * or the helper methods contained in this class to make recipes. + * For an example of how you might do this, see {@link net.nuclearteam.createnuclear.foundation.data.recipe.CNSnowPowderRecipeGen}. + * Needs to be added to a registered recipe provider to do anything, see {@link net.nuclearteam.createnuclear.foundation.data.recipe.CNRecipeProvider} + */ +public abstract class SnowPowderRecipeGen extends StandardProcessingRecipeGen { + public GeneratedRecipe convert(ItemLike input, ItemLike result) { + return convert(() -> Ingredient.of(input), () -> result); + } + + public GeneratedRecipe convert(Supplier input, Supplier result) { + return create(asResource(RegisteredObjectsHelper.getKeyOrThrow(result.get().asItem()) + .getPath()), + p -> p.withItemIngredients(input.get()) + .output(result.get())); + } + + public SnowPowderRecipeGen(PackOutput output, CompletableFuture registries, String defaultNamespace) { + super(output, registries, defaultNamespace); + } + + @Override + protected CNRecipeTypes getRecipeType() { + return CNRecipeTypes.SNOW_POWDER; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/api/multiblock/IMultiblockController.java b/src/main/java/net/nuclearteam/createnuclear/api/multiblock/IMultiblockController.java new file mode 100644 index 0000000..7a9478d --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/api/multiblock/IMultiblockController.java @@ -0,0 +1,8 @@ +package net.nuclearteam.createnuclear.api.multiblock; + +import net.minecraft.core.Direction; + +public interface IMultiblockController { + void setMultiblockFacing(Direction f); + Direction getMultiblockFacing(); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/api/multiblock/MultiBlockManagerBeta.java b/src/main/java/net/nuclearteam/createnuclear/api/multiblock/MultiBlockManagerBeta.java index ce79b01..d74b16a 100644 --- a/src/main/java/net/nuclearteam/createnuclear/api/multiblock/MultiBlockManagerBeta.java +++ b/src/main/java/net/nuclearteam/createnuclear/api/multiblock/MultiBlockManagerBeta.java @@ -4,6 +4,8 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; import java.util.ArrayList; import java.util.List; @@ -17,7 +19,7 @@ public void register(String id, T data, IMultiBlockPattern blockPattern) { structures.add(new BlockPattern<>(id, data, blockPattern)); } - public BlockPattern findStructure(Level level, BlockPos pos) { + public BlockPattern findStructure(Level level, BlockPos pos, IMultiblockController entity) { List directions = new ArrayList<>(); directions.add(Direction.NORTH); directions.add(Direction.WEST); @@ -26,8 +28,11 @@ public BlockPattern findStructure(Level level, BlockPos pos) { for (Direction direction : directions) { for (BlockPattern structure : structures) { - var result = structure.structure().matches(level, pos, direction); - if (result) return structure; + boolean result = structure.structure().matches(level, pos, direction); + if (result){ + entity.setMultiblockFacing(direction.getCounterClockWise()); + return structure; + } } } diff --git a/src/main/java/net/nuclearteam/createnuclear/api/multiblock/TypeMultiblock.java b/src/main/java/net/nuclearteam/createnuclear/api/multiblock/TypeMultiblock.java index e22beb1..9f52c6b 100644 --- a/src/main/java/net/nuclearteam/createnuclear/api/multiblock/TypeMultiblock.java +++ b/src/main/java/net/nuclearteam/createnuclear/api/multiblock/TypeMultiblock.java @@ -1,5 +1,26 @@ package net.nuclearteam.createnuclear.api.multiblock; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; + public enum TypeMultiblock { - REACTOR + REACTOR_T1(5), + REACTOR_T2(7), + REACTOR_T3(9) + ; + + private final int size; + private final String name; + + TypeMultiblock(int size) { + this.size = size; + this.name = CreateNuclearLang.asId(name()); + } + + public int getSize() { + return this.size; + } + + public String getName() { + return this.name; + } } diff --git a/src/main/java/net/nuclearteam/createnuclear/api/multiblock/fluid/ReactorFluidType.java b/src/main/java/net/nuclearteam/createnuclear/api/multiblock/fluid/ReactorFluidType.java new file mode 100644 index 0000000..949378a --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/api/multiblock/fluid/ReactorFluidType.java @@ -0,0 +1,198 @@ +package net.nuclearteam.createnuclear.api.multiblock.fluid; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.Holder; +import net.minecraft.core.Holder.Reference; +import net.minecraft.core.HolderSet; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.RegistryCodecs; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.RegistryFixedCodec; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; +import net.neoforged.neoforge.fluids.FluidStack; +import net.nuclearteam.createnuclear.api.CreateNuclearRegistries; +import net.nuclearteam.createnuclear.api.ReactorFluidTypesValue; +import net.nuclearteam.createnuclear.content.multiblock.fluid.CNReactorFluidTypes; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + + +/** + * Represents a reactor fluid type used by the mod's multiblock. + *

+ * A {@code ReactorFluidType} holds the single fluid that identifies this + * fluid type, along with its heat-related and efficiency values. + */ +public record ReactorFluidType(Holder fluid, int maxHeat, int efficiency, boolean useConfig) { + public ReactorFluidType(Holder fluid, int maxHeat, int efficiency) { + this(fluid, maxHeat, efficiency, false); + } + + /** Serialization codec for saving/loading {@link ReactorFluidType} instances. */ + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + RegistryFixedCodec.create(Registries.FLUID).fieldOf("fluid").forGetter(ReactorFluidType::fluid), + Codec.INT.fieldOf("maxHeat").forGetter(ReactorFluidType::maxHeat), + Codec.INT.fieldOf("efficiency").forGetter(ReactorFluidType::efficiency) + ).apply(i, ReactorFluidType::new)); + + /** + * Searches the {@code FLUID_TYPE} registry for a {@link ReactorFluidType} + * matching the provided {@link Fluid}. + * + * @param registryAccess registry access for the world + * @param fluid the fluid to look up + * @return an {@link Optional} containing a {@link Reference} to the matching + * {@code ReactorFluidType} if found, otherwise {@link Optional#empty()} + */ + public static Optional> getTypeForFluid(RegistryAccess registryAccess, Fluid fluid) { + ResourceLocation fluidKey = BuiltInRegistries.FLUID.getKey(fluid); + if (fluidKey == null) return Optional.empty(); + + return registryAccess.lookupOrThrow(CreateNuclearRegistries.FLUID_TYPE) + .listElements() + .filter(ref -> ref.value().fluid.unwrapKey() + .map(k -> k.location().equals(fluidKey)) + .orElse(false) + ) + .findFirst(); + } + + /** + * Resolves the {@code ReactorFluidType} for a given {@link Fluid}. + *

+ * The resolution first checks the world's registries, then falls back to + * {@link ReactorFluidTypesValue}, and finally returns the registry fallback + * value if none is found. + * + * @param fluid the fluid whose reactor type should be resolved + * @param world the level used to access registries + * @return the resolved {@code ReactorFluidType} (never {@code null}) + */ + public static ReactorFluidType resolveReactorFluidType(Fluid fluid, Level world) { + return ReactorFluidType.getTypeForFluid(world.registryAccess(), fluid) + .map(Reference::value) + .orElseGet(() -> { + ReactorFluidType fromFluid = ReactorFluidTypesValue.getReactorFluidType(fluid); + return fromFluid.isNotEmptyFluid() + ? fromFluid + : world.registryAccess() + .registryOrThrow(CreateNuclearRegistries.FLUID_TYPE) + .getHolderOrThrow(CreateNuclearRegistries.FALLBACK_FLUID) + .value(); + }); + } + + + /** + * Returns whether this {@code ReactorFluidType} has an associated fluid + * (i.e. is not the empty/sentinel fluid). + * + * @return {@code true} if a real fluid is defined, {@code false} otherwise + */ + public boolean isNotEmptyFluid() { + return this.fluid.value() != Fluids.EMPTY; + } + + /** + * Fluent builder for creating an immutable {@link ReactorFluidType} instance. + *

+ * Use the configuration methods and class {@link #build()} to obtain the + * resulting instance. + */ + public static class Builder { + private Holder fluid = null; + private int maxHeat = 0; + private int efficiency = 0; + private boolean maxHeatSet = false; + private boolean efficiencySet = false; + + /** + * Sets the maximum heat value for the built {@link ReactorFluidType}. + * + * @param maxHeat maximum heat value + * @return this builder + */ + public Builder maxHeat(int maxHeat) { + this.maxHeat = maxHeat; + this.maxHeatSet = true; + return this; + } + + /** + * Sets the efficiency value for the built {@link ReactorFluidType}. + * + * @param efficiency efficiency value + * @return this builder + */ + public Builder efficiency(int efficiency) { + this.efficiency = efficiency; + this.efficiencySet = true; + return this; + } + + /** + * Sets the fluid identifying this type from a {@link FluidStack}. + * + * @param fluidStack the fluid stack providing the fluid + * @return this builder + */ + public Builder fluid(FluidStack fluidStack) { + return fluid(fluidStack.getFluid()); + } + + /** + * Sets the fluid identifying this type. Calling this again replaces + * the previously set fluid. + * + * @param fluid the fluid to associate with this type + * @return this builder + */ + public Builder fluid(Fluid fluid) { + this.fluid = fluid.builtInRegistryHolder(); + return this; + } + + /** + * Builds the immutable {@link ReactorFluidType} instance. + * + * @return the created instance + * @throws IllegalStateException if required fields are missing + */ + public ReactorFluidType build() { + List missing = new ArrayList<>(); + if (fluid == null) missing.add("fluid"); + if (!maxHeatSet) missing.add("maxHeat"); + if (!efficiencySet) missing.add("efficiency"); + + if (!missing.isEmpty()) + throw new IllegalStateException("Missing required ReactorFluidType fields: " + String.join(", ", missing)); + + return new ReactorFluidType(fluid, maxHeat, efficiency); + } + } + + @Override + public @NotNull String toString() { + String fluidNames = this.fluid.unwrapKey() + .map(k -> k.location().toString()) + .orElseGet(() -> { + ResourceLocation rl = BuiltInRegistries.FLUID.getKey(this.fluid.value()); + return rl != null ? rl.toString() : this.fluid.value().toString(); + }); + + return "ReactorFluidType{" + + "fluids=[" + fluidNames + "]," + + "maxHeat=" + maxHeat() + "," + + "efficiency=" + efficiency() + + "}"; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/api/multiblock/rods/RodType.java b/src/main/java/net/nuclearteam/createnuclear/api/multiblock/rods/RodType.java new file mode 100644 index 0000000..4164f3c --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/api/multiblock/rods/RodType.java @@ -0,0 +1,376 @@ +package net.nuclearteam.createnuclear.api.multiblock.rods; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.Holder; +import net.minecraft.core.Holder.Reference; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.RegistryFixedCodec; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.api.CreateNuclearRegistries; +import net.nuclearteam.createnuclear.api.ItemRodTypesValue; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.function.Supplier; + +/** + * Represents a rod type used by the mod's multiblock. + *

+ * A {@code RodType} holds the single item that represents this rod type, + * heat-related values, a timing value, and a {@link TypeRod} indicating the + * category (fuel, cooler, or mixed). + */ +@MethodsReturnNonnullByDefault +public record RodType(Holder item, + Supplier baseRodHeat, + Supplier proximityRodHeat, + Supplier rodTimer, + Supplier ratio, + TypeRod type) { + + public RodType(Holder item, + int baseRodHeat, float proximityRodHeat, + int rodTimer, TypeRod type) { + this(item, baseRodHeat, proximityRodHeat, rodTimer, type, 1); + } + + public RodType(Holder item, + int baseRodHeat, float proximityRodHeat, + int rodTimer, TypeRod type, int ratio) { + this(item, () -> baseRodHeat, () -> proximityRodHeat, () -> rodTimer, () -> ratio, type); + } + + /** + * Serialization codec for saving/loading {@link RodType} instances. + */ + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + RegistryFixedCodec.create(Registries.ITEM).fieldOf("item").forGetter(RodType::item), + Codec.INT.fieldOf("baseRodHeat").forGetter(rt -> rt.baseRodHeat().get()), + Codec.FLOAT.fieldOf("proximityRodHeat").forGetter(rt -> rt.proximityRodHeat().get()), + Codec.INT.fieldOf("rodTimer").forGetter(rt -> rt.rodTimer().get()), + StringRepresentable.fromEnum(TypeRod::values).fieldOf("type").forGetter(RodType::type), + Codec.INT.optionalFieldOf("ratio", 1).forGetter(rt -> rt.ratio().get()) + ).apply(i, RodType::new)); + + /** + * Searches the {@code ROD_TYPE} registry for a {@link RodType} matching the + * provided {@link Item}. + * + * @param registryAccess registry access for the world + * @param item the item to look up + * @return an {@link Optional} containing a {@link Reference} to the matching + * {@code RodType} if found, otherwise {@link Optional#empty()} + */ + public static Optional> getTypeForItem(RegistryAccess registryAccess, Item item) { + return registryAccess.lookupOrThrow(CreateNuclearRegistries.ROD_TYPE) + .listElements() + .filter(ref -> ref.value().item.equals(item.builtInRegistryHolder())) + .findFirst(); + } + + /** + * Resolves the {@code RodType} for a given {@link Item}. The method first + * checks the world's registries, then falls back to {@link ItemRodTypesValue}, + * and lastly returns a fallback registry value if none is found. + * + * @param item the item whose rod type should be resolved + * @param world the world (level) used to access registries + * @return the resolved {@code RodType} (never {@code null}) + */ + public static RodType resolveRodType(Item item, Level world) { + return RodType.getTypeForItem(world.registryAccess(), item) + .map(Holder.Reference::value) + .orElseGet(() -> { + RodType fromItem = ItemRodTypesValue.getRodType(item); + return fromItem.isNotEmptyItem() + ? fromItem + : world.registryAccess() + .registryOrThrow(CreateNuclearRegistries.ROD_TYPE) + .getHolderOrThrow(CreateNuclearRegistries.FALLBACK_ROD) + .value(); + }); + } + + /** + * Returns whether this {@code RodType} has an associated item (i.e. is + * not the empty/sentinel item). + * + * @return {@code true} if a real item is defined, {@code false} otherwise + */ + public boolean isNotEmptyItem() { + return this.item.value() != Items.AIR; + } + + /** + * Fluent builder for creating an immutable {@link RodType} instance. + *

+ * Every heat/timing value ({@code baseRodHeat}, {@code proximityRodHeat}, + * {@code rodTimer}, {@code ratio}) can be set either as a fixed + * primitive (evaluated once, at build time) or as a {@link Supplier} + * (re-evaluated on every call to the corresponding {@link RodType} + * accessor). The primitive overloads are pure convenience: they simply + * wrap the given value in a constant supplier, e.g. + * {@code baseRodHeat(5)} is equivalent to {@code baseRodHeat(() -> 5)}. + * Use the {@link Supplier} overloads to back a value with a live source + * such as a config option (see {@code CNItems} for examples), so that + * changes are picked up without rebuilding the {@code RodType}. + *

+ * {@code item}, {@code type}, {@code baseRodHeat}, {@code proximityRodHeat} + * and {@code rodTimer} are required; {@code ratio} defaults to a + * constant {@code 1} and never needs to be set explicitly. Call + * {@link #build()} once all required values are configured. + */ + public static class Builder { + private Holder item = null; + private Supplier baseRodHeat = null; + private Supplier proximityRodHeat = null; + private Supplier rodTimer = null; + private Supplier ratio = () -> 1; + private TypeRod type = TypeRod.NONE; + + /** + * Sets a fixed base heat value, evaluated once at build time. + * Equivalent to {@code baseRodHeat(() -> baseRodHeat)}. + * + * @param baseRodHeat constant base heat value + * @return this builder + */ + public Builder baseRodHeat(int baseRodHeat) { + return baseRodHeat(() -> baseRodHeat); + } + + /** + * Sets a dynamic base heat value, re-evaluated every time + * {@link RodType#baseRodHeat()} is called (e.g. to reflect a live + * config option instead of a value frozen at registration time). + * + * @param baseRodHeat supplier producing the base heat value on demand + * @return this builder + */ + public Builder baseRodHeat(Supplier baseRodHeat) { + this.baseRodHeat = baseRodHeat; + return this; + } + + /** + * Sets a fixed proximity heat value (heat contributed by nearby rods), + * evaluated once at build time. + * Equivalent to {@code proximityRodHeat(() -> proximityRodHeat)}. + * + * @param proximityRodHeat constant proximity heat value + * @return this builder + */ + public Builder proximityRodHeat(float proximityRodHeat) { + return proximityRodHeat(() -> proximityRodHeat) ; + } + + /** + * Sets a dynamic proximity heat value, re-evaluated every time + * {@link RodType#proximityRodHeat()} is called. + * + * @param proximityRodHeat supplier producing the proximity heat value on demand + * @return this builder + */ + public Builder proximityRodHeat(Supplier proximityRodHeat) { + this.proximityRodHeat = proximityRodHeat; + return this; + } + + /** + * Sets a fixed timer (duration) for the rod's behavior, evaluated + * once at build time. Equivalent to {@code rodTimer(() -> rodTimer)}. + * + * @param rodTimer constant duration in ticks or mod-specific units + * @return this builder + */ + public Builder rodTimer(int rodTimer) { + return rodTimer(() -> rodTimer); + } + + /** + * Sets a dynamic timer (duration) for the rod's behavior, + * re-evaluated every time {@link RodType#rodTimer()} is called. + * + * @param rodTimer supplier producing the duration on demand + * @return this builder + */ + public Builder rodTimer(Supplier rodTimer) { + this.rodTimer = rodTimer; + return this; + } + + /** + * Sets a fixed heat ratio, evaluated once at build time. Optional: + * defaults to a constant {@code 1} if never called. + * Equivalent to {@code ratio(() -> ratio)}. + * + * @param ratio constant heat ratio value + * @return this builder + */ + public Builder ratio(int ratio) { + return ratio(() -> ratio); + } + + /** + * Sets a dynamic heat ratio, re-evaluated every time + * {@link RodType#ratio()} is called. Optional: defaults to a + * constant {@code 1} if never called. + * + * @param ratio supplier producing the heat ratio on demand + * @return this builder + */ + public Builder ratio(Supplier ratio) { + this.ratio = ratio; + return this; + } + + /** + * Sets the rod category directly. Prefer the {@link #coolerRodType()} + * and {@link #fuelRodType()} convenience methods for the common + * cases; use this overload only to set {@link TypeRod#NONE} + * explicitly (e.g. for a fallback/sentinel rod type). + * + * @param type the rod category to assign + * @return this builder + */ + public Builder type(TypeRod type) { + this.type = type; + return this; + } + + /** + * Sets the rod type to {@link TypeRod#COOLER}. + * + * @return this builder + */ + public Builder coolerRodType() { + return type(TypeRod.COOLER); + } + + /** + * Sets the rod type to {@link TypeRod#FUEL}. + * + * @return this builder + */ + public Builder fuelRodType() { + return type(TypeRod.FUEL); + } + + /** + * Sets the item that represents this rod type. Calling this again + * replaces the previously set item. + * + * @param item the item to associate with this rod type + * @return this builder + */ + public Builder item(ItemLike item) { + this.item = item.asItem().builtInRegistryHolder(); + return this; + } + + /** + * Builds the immutable {@link RodType} instance. + *

+ * Validates that {@code item} and {@code type}, {@code baseRodHeat}, + * {@code proximityRodHeat} and {@code rodTimer} have all been set + * (either as a fixed value or as a dynamic {@link Supplier}); + * {@code ratio} is exempt since it defaults to a constant + * {@code 1}. + * + * @throws IllegalStateException if one or more required fields are missing, + * naming every missing field in the exception message + * @return the created instance + */ + public RodType build() { + List missing = new ArrayList<>(); + if (item == null) missing.add("item"); + if (type == null) missing.add("type"); + if (baseRodHeat == null) missing.add("baseRodHeat"); + if (proximityRodHeat == null) missing.add("proximityRodHeat"); + if (rodTimer == null) missing.add("rodTimer"); + + if (!missing.isEmpty()) + throw new IllegalStateException("Missing required RodType fields: " + String.join(", ", missing)); + + return new RodType(item, baseRodHeat, proximityRodHeat, rodTimer, ratio, type); + } + } + + public enum TypeRod implements StringRepresentable { + /** + * Fuel rod: generates heat via reaction. + */ + FUEL, + /** + * Cooler rod: reduces or absorbs heat. + */ + COOLER, + /** + * Sentinel value for the fallback/default rod type — no real category. + */ + NONE + ; + + @Override + public String getSerializedName() { + return name(); + } + } + + public static final class TypeRodPredicate { + public static final Predicate IS_NOT_NULL = Objects::nonNull; + + public static boolean isFuel(ItemStack stack, Level level) { + return IS_NOT_NULL.test(stack) && RodType.resolveRodType(stack.getItem(), level).type == TypeRod.FUEL; + } + + public static boolean isFuel(RodType rodType) { + return rodType != null && rodType.type() == TypeRod.FUEL; + } + + public static boolean isCooled(ItemStack stack, Level level) { + return IS_NOT_NULL.test(stack) && RodType.resolveRodType(stack.getItem(), level).type == TypeRod.COOLER; + } + + public static boolean isCooled(RodType rodType) { + return rodType != null && rodType.type() == TypeRod.COOLER; + } + + public static String tooltipKey(ItemStack stack, Level level) { + if (!IS_NOT_NULL.test(stack)) return "unknown"; + if (isFuel(stack, level)) return "fuel"; + if (isCooled(stack, level)) return "cooled"; + return "unknown"; + } + } + + @Override + public String toString() { + String itemName = this.item.unwrapKey() + .map(k -> k.location().toString()) + .orElseGet(() -> { + ResourceLocation rl = BuiltInRegistries.ITEM.getKey(this.item.value()); + return rl != null ? rl.toString() : this.item.value().toString(); + }); + + return "RodType [item: " + itemName + + ", baseRodHeat: " + this.baseRodHeat().get() + + ", proximityRodHeat: " + this.proximityRodHeat().get() + + ", rodTimer: " + this.rodTimer().get() + + ", ratio: " + this.ratio().get() + + ", type: " + this.type() + "]"; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/api/radiation/IRadiationSource.java b/src/main/java/net/nuclearteam/createnuclear/api/radiation/IRadiationSource.java new file mode 100644 index 0000000..b55b90b --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/api/radiation/IRadiationSource.java @@ -0,0 +1,9 @@ +package net.nuclearteam.createnuclear.api.radiation; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; + +public interface IRadiationSource { + double getRadiation(ItemStack stack, LivingEntity entity); +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/api/radiation/RadiationRegistry.java b/src/main/java/net/nuclearteam/createnuclear/api/radiation/RadiationRegistry.java new file mode 100644 index 0000000..261bfcf --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/api/radiation/RadiationRegistry.java @@ -0,0 +1,98 @@ +package net.nuclearteam.createnuclear.api.radiation; + +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.biome.Biome; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +public class RadiationRegistry { + private static final Map ITEM_VALUE = new HashMap<>(); + private static final Map, Double> TAG_VALUE = new HashMap<>(); + private static final Map, Double> BIOME_VALUE = new HashMap<>(); + + private RadiationRegistry() {} + + public static Builder register() { + return new Builder(); + } + + public static double get(ItemStack stack) { + Item item = stack.getItem(); + + Double value = ITEM_VALUE.get(item); + if (value != null) return value; + + for (Entry, Double> entry : TAG_VALUE.entrySet()) { + if (stack.is(entry.getKey())) { + return entry.getValue(); + } + } + + return 0D; + } + + public static double get(ResourceKey stack) { + Double value = BIOME_VALUE.get(stack); + if (value != null) return value; + + return 0D; + } + + public static double getRadiation(ItemStack stack, @Nullable LivingEntity entity) { + return get(stack) * stack.getCount(); + } + public static double getRadiation(ResourceKey biome, @Nullable LivingEntity entity) { + return get(biome); + } + + public static class Builder { + private Item item; + private TagKey tag; + private ResourceKey biome; + private double value; + + public Builder item(Item item) { + this.item = item; + return this; + } + + public Builder tag(TagKey tag) { + this.tag = tag; + return this; + } + + public Builder biome(ResourceKey biome) { + this.biome = biome; + return this; + } + + public Builder value(double value) { + this.value = value; + return this; + } + + public void build() { + if (item != null) { + if (item instanceof IRadiationSource) + throw new IllegalStateException("Item " + item + " implements IRadiationSource and should not also be registered in RadiationRegistry (would cause double counting)."); + ITEM_VALUE.put(item, value); + } + + if (tag != null) { + TAG_VALUE.put(tag, value); + } + + if (biome != null) { + BIOME_VALUE.put(biome, value); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/compat/Mods.java b/src/main/java/net/nuclearteam/createnuclear/compat/Mods.java new file mode 100644 index 0000000..cba6eec --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/compat/Mods.java @@ -0,0 +1,86 @@ +package net.nuclearteam.createnuclear.compat; + +import net.createmod.catnip.lang.Lang; +import net.createmod.catnip.registry.RegisteredObjectsHelper; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.Block; +import net.neoforged.fml.loading.LoadingModList; + +import java.util.Optional; +import java.util.function.Supplier; + +public enum Mods { + ALEXS_CAVE("alexscaves") + ; + + private final String id; + private final boolean isLoaded; + + Mods(String name) { + id = Lang.asId(name); + isLoaded = LoadingModList.get().getModFileById(id) != null; + } + + Mods() { + id = Lang.asId(name()); + isLoaded = LoadingModList.get().getModFileById(id) != null; + } + + public String id() { + return id; + } + + public ResourceLocation rl(String path) { + return ResourceLocation.fromNamespaceAndPath(id, path); + } + + public Block getBlock(String id) { + return BuiltInRegistries.BLOCK.get(rl(id)); + } + + public Item getItem(String id) { + return BuiltInRegistries.ITEM.get(rl(id)); + } + + public boolean contains(ItemLike entry) { + if (!isLoaded()) + return false; + Item asItem = entry.asItem(); + return asItem != null && RegisteredObjectsHelper.getKeyOrThrow(asItem) + .getNamespace() + .equals(id); + } + + /** + * @return a boolean of whether the mod is loaded or not based on mod id + */ + public boolean isLoaded() { + return isLoaded; + } + + /** + * Simple hook to run code if a mod is installed + * + * @param toRun will be run only if the mod is loaded + * @return Optional.empty() if the mod is not loaded, otherwise an Optional of the return value of the given supplier + */ + public Optional runIfInstalled(Supplier> toRun) { + if (isLoaded()) + return Optional.of(toRun.get().get()); + return Optional.empty(); + } + + /** + * Simple hook to execute code if a mod is installed + * + * @param toExecute will be executed only if the mod is loaded + */ + public void executeIfInstalled(Supplier toExecute) { + if (isLoaded()) { + toExecute.get().run(); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/compat/alexscave/AlexscaveCompat.java b/src/main/java/net/nuclearteam/createnuclear/compat/alexscave/AlexscaveCompat.java new file mode 100644 index 0000000..3fa1d95 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/compat/alexscave/AlexscaveCompat.java @@ -0,0 +1,66 @@ +package net.nuclearteam.createnuclear.compat.alexscave; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +/** + * The mod doesn't exist for 1.21.1. + */ +public class AlexscaveCompat { + public AlexscaveCompat() {} + + public boolean MobSpawn(BlockState state, Level level, BlockPos.MutableBlockPos carve, float itemDropModifier, Explosion dummyExplosion){ +// if(state.is(ACBlockRegistry.TREMORZILLA_EGG.get()) && state.getBlock() instanceof TremorzillaEggBlock tremorzillaEggBlock){ +// tremorzillaEggBlock.spawnDinosaurs(level, carve, state); +// return true; +// } +// else if (AlexsCaves.COMMON_CONFIG.nukesSpawnItemDrops.get() && random.nextFloat() < itemDropModifier && state.getFluidState().isEmpty()) { +// level.destroyBlock(carve, true); +// } else { +// state.onBlockExploded(level, carve, dummyExplosion); +// } + return false; + } + +// public boolean isRaycat(LivingEntity entity) { +// return entity instanceof RaycatEntity; +// } +// +// public boolean isTremorzilla(LivingEntity entity){ +// return entity instanceof TremorzillaEntity; +// } +// +// public boolean ACResConfig(){ +// return AlexsCaves.COMMON_CONFIG.nukeMaxBlockExplosionResistance.get() <= 0; +// } + +// public boolean ACDestroyable(BlockState state) { +// return !state.is(ACTagRegistry.NUKE_PROOF) && +// (state.getBlock().getExplosionResistance() < AlexsCaves.COMMON_CONFIG.nukeMaxBlockExplosionResistance.get() +// || state.is(ACBlockRegistry.TREMORZILLA_EGG.get())); +// } + + public void NukeParam() { +// ((ClientProxy) AlexsCaves.PROXY).renderNukeSkyDarkFor = 70; +// ((ClientProxy) AlexsCaves.PROXY).muteNonNukeSoundsFor = 50; + } + +// public SoundEvent[] GetACSounds(){ +// return new SoundEvent[] { +// ACSoundRegistry.LARGE_NUCLEAR_EXPLOSION.get(), +// ACSoundRegistry.NUCLEAR_EXPLOSION.get(), +// ACSoundRegistry.NUCLEAR_EXPLOSION_RINGING.get(), +// ACSoundRegistry.NUCLEAR_EXPLOSION_RUMBLE.get() +// }; +// } + +// public boolean GetACConfig(){ +// return AlexsCaves.CLIENT_CONFIG.nuclearBombFlash.get(); +// } + + public void UpdateACProxy() { +// ((ClientProxy) AlexsCaves.PROXY).renderNukeFlashFor = 16; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/compat/jei/CreateNuclearJEI.java b/src/main/java/net/nuclearteam/createnuclear/compat/jei/CreateNuclearJEI.java index fa22835..67eaca8 100644 --- a/src/main/java/net/nuclearteam/createnuclear/compat/jei/CreateNuclearJEI.java +++ b/src/main/java/net/nuclearteam/createnuclear/compat/jei/CreateNuclearJEI.java @@ -32,6 +32,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.item.alchemy.Potion; import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.item.crafting.Recipe; @@ -43,7 +44,9 @@ import net.nuclearteam.createnuclear.CNRecipeTypes; import net.nuclearteam.createnuclear.CreateNuclear; import net.nuclearteam.createnuclear.compat.jei.category.FanEnrichedCategory; +import net.nuclearteam.createnuclear.compat.jei.category.FanSnowPowderCategory; import net.nuclearteam.createnuclear.content.kinetics.fan.processing.EnrichedRecipe; +import net.nuclearteam.createnuclear.content.kinetics.fan.processing.SnowPowderRecipe; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; @@ -72,7 +75,13 @@ private void loadCategories() { .catalystStack(ProcessingViaFanCategory.getFan("fan_enriched")) .doubleItemIcon(AllItems.PROPELLER.get(), CNBlocks.ENRICHING_CAMPFIRE.get()) .emptyBackground(178, 72) - .build("fan_enriched", FanEnrichedCategory::new) + .build("fan_enriched", FanEnrichedCategory::new), + snow_powder = builder(SnowPowderRecipe.class) + .addTypedRecipes(CNRecipeTypes.SNOW_POWDER::getType) + .catalystStack(ProcessingViaFanCategory.getFan("fan_snow_powder")) + .doubleItemIcon(AllItems.PROPELLER.get(), Items.POWDER_SNOW_BUCKET) + .emptyBackground(178, 72) + .build("fan_snow_powder", FanSnowPowderCategory::new) ; } diff --git a/src/main/java/net/nuclearteam/createnuclear/compat/jei/category/FanSnowPowderCategory.java b/src/main/java/net/nuclearteam/createnuclear/compat/jei/category/FanSnowPowderCategory.java new file mode 100644 index 0000000..45aa509 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/compat/jei/category/FanSnowPowderCategory.java @@ -0,0 +1,40 @@ +package net.nuclearteam.createnuclear.compat.jei.category; + +import com.simibubi.create.compat.jei.category.ProcessingViaFanCategory; +import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import net.createmod.catnip.gui.element.GuiGameElement; +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.block.Blocks; +import net.nuclearteam.createnuclear.content.kinetics.fan.processing.SnowPowderRecipe; + +import javax.annotation.ParametersAreNonnullByDefault; + +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +public class FanSnowPowderCategory extends ProcessingViaFanCategory.MultiOutput { + public FanSnowPowderCategory(Info info) { + super(info); + } + + @Override + protected AllGuiTextures getBlockShadow() { + return AllGuiTextures.JEI_LIGHT; + } + + @Override + protected void renderAttachedBlock(GuiGraphics graphics) { + GuiGameElement.of(Blocks.POWDER_SNOW.defaultBlockState()) + .scale(SCALE) + .atLocal(0, 0, 2) + .lighting(AnimatedKinetics.DEFAULT_LIGHTING) + .render(graphics); + } + + @Override + public Component getTitle() { + return Component.translatable("createnuclear.snow_powder.fan.recipe"); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/biome/BiomeIrradiationExtractorItem.java b/src/main/java/net/nuclearteam/createnuclear/content/biome/BiomeIrradiationExtractorItem.java new file mode 100644 index 0000000..0f32378 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/biome/BiomeIrradiationExtractorItem.java @@ -0,0 +1,97 @@ +package net.nuclearteam.createnuclear.content.biome; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.CNDataComponents; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.BiomeIrradiationService; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; + +@ParametersAreNonnullByDefault +public class BiomeIrradiationExtractorItem extends Item { + public static final String TAG = "biome_restore"; + private static final int CHARGE_PER_CLICK = 1; + + public BiomeIrradiationExtractorItem(Properties pProperties) { + super(pProperties); + } + + @Override + public InteractionResultHolder use(Level level, Player player, InteractionHand interactionHand) { + ItemStack stack = player.getItemInHand(interactionHand); + + if (level.isClientSide || !(level instanceof ServerLevel serverLevel)) { + return InteractionResultHolder.success(stack); + } + + if (getCharge(stack) >= getMaxCharge()) { + return InteractionResultHolder.pass(stack); + } + + boolean restored = BiomeIrradiationService.restoreArea(serverLevel, player.blockPosition()); + if (!restored) { + return InteractionResultHolder.pass(stack); + } + + ItemStack charged = stack.copyWithCount(1); + addCharge(charged, CHARGE_PER_CLICK); + + stack.shrink(1); + if (stack.isEmpty()) { + return InteractionResultHolder.success(charged); + } + + if (!player.getInventory().add(charged)) { + player.drop(charged, false); + } + return InteractionResultHolder.success(stack); + } + + @Override + public void appendHoverText(ItemStack stack, TooltipContext context, List tooltipComponents, TooltipFlag tooltipFlag) { + super.appendHoverText(stack, context, tooltipComponents, tooltipFlag); + if (tooltipFlag.isAdvanced() && getCharge(stack) > 0) { + tooltipComponents.add( + CreateNuclearLang + .translateDirect("tooltip.biome_irradiation_extractor." + TAG, getCharge(stack), getMaxCharge()) + .withStyle(ChatFormatting.GRAY) + ); + } + } + + @Override + public int getMaxStackSize(ItemStack stack) { + return getCharge(stack) > 0 ? 1 : this.getDefaultMaxStackSize(); + } + + public static int getCharge(ItemStack stack) { + return getChargeDataComponents(stack, 0); + } + + public static int getMaxCharge() { + return CNConfigs.server().biomeRestore.maxCharge.get(); + } + + public static void addCharge(ItemStack stack, int amount) { + int current = getCharge(stack); + int next = Mth.clamp(current + amount, 0, getMaxCharge()); + + stack.set(CNDataComponents.CHARGE_BIOME_IRRADIATION_EXTRACTOR, next); + } + + public static int getChargeDataComponents(ItemStack stack, int defaultValue) { + return stack.getOrDefault(CNDataComponents.CHARGE_BIOME_IRRADIATION_EXTRACTOR, defaultValue); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/AnimalUtil.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/AnimalUtil.java new file mode 100644 index 0000000..0a1aecc --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/AnimalUtil.java @@ -0,0 +1,39 @@ +package net.nuclearteam.createnuclear.content.contraptions.irradiated; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.CNItems; + +import java.util.function.Predicate; + +public class AnimalUtil { + private AnimalUtil() {} + + public static boolean isFood(ItemStack stack, Ingredient foodItems) { + return isFood(stack, foodItems, $ -> true); + } + + public static boolean isFood(ItemStack stack, Ingredient foodItems, Predicate extraTest) { + if (stack.is(CNItems.YELLOWCAKE.get())) { + return true; + } + + return foodItems.test(stack) || extraTest.test(stack); + } + + /** + * Taming for irradiated creatures is still work in progress: rather than actually + * taming the mob, this informs the player and consumes the interaction. + */ + public static InteractionResult blockTamingWip(Player player, Level level) { + if (!level.isClientSide) { + player.sendSystemMessage(Component.translatable("irradiated.taming.wip")); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/CNModelLayers.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/CNModelLayers.java index e62c785..b812a32 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/CNModelLayers.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/CNModelLayers.java @@ -12,6 +12,9 @@ public class CNModelLayers { public static final ModelLayerLocation IRRADIATED_CHICKEN = register("irradiated_chicken"); public static final ModelLayerLocation IRRADIATED_WOLF = register("irradiated_wolf"); public static final ModelLayerLocation IRRADIATED_CAT = register("irradiated_cat"); + public static final ModelLayerLocation IRRADIATED_COW = register("irradiated_cow"); + + public static final ModelLayerLocation ANTI_RADIATION_ARMOR = register("anti_radiation_armor"); private static ModelLayerLocation register(String path) { return register(path, "main"); diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/IrradiatedAnimal.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/IrradiatedAnimal.java new file mode 100644 index 0000000..0d6df37 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/IrradiatedAnimal.java @@ -0,0 +1,90 @@ +package net.nuclearteam.createnuclear.content.contraptions.irradiated; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.BlockTags; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.EntityEvent; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.event.EventHooks; + +import java.util.HashMap; +import java.util.Map; + +public interface IrradiatedAnimal { + Map, EntityType> VANILLA_TO_IRRADIATED = new HashMap<>(); + + EntityType getNormalVariant(); + + default void readFromVanilla(Animal animal) {} + + default void writeToVanilla(Animal animal) {} + + boolean isConverting(); + + void setConverting(); + + void setConversionTime(int conversionTime); + + int getConversionTime(); + + default void startConverting(int conversionTime) { + Animal animal = (Animal) this; + + setConversionTime(conversionTime); + setConverting(); + animal.removeEffect(MobEffects.WEAKNESS); + animal.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, conversionTime, Math.min(animal.level().getDifficulty().getId() - 1, 0))); + animal.level().broadcastEntityEvent(animal, EntityEvent.ZOMBIE_CONVERTING); + } + + default void finishConversion(ServerLevel level) { + Animal irradiatedAnimal = (Animal) this; + Animal vanillaAnimal = irradiatedAnimal.convertTo(getNormalVariant(), false); + + if (vanillaAnimal != null) { + vanillaAnimal.finalizeSpawn(level, level.getCurrentDifficultyAt(vanillaAnimal.blockPosition()), MobSpawnType.CONVERSION, null); + writeToVanilla(vanillaAnimal); + vanillaAnimal.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); + + if (!irradiatedAnimal.isSilent()) { + level.levelEvent(null, LevelEvent.SOUND_ZOMBIE_CONVERTED, irradiatedAnimal.blockPosition(), 0); + } + + EventHooks.onLivingConvert(irradiatedAnimal, vanillaAnimal); + } + } + + default int getConversionProgress() { + int progress = 1; + Animal animal = (Animal) this; + + if (animal.getRandom().nextFloat() < 0.01F) { + int buffCount = 0; + BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); + + for (int x = (int) animal.getX() - 4; x < animal.getX() + 4 && buffCount < 14; ++x) { + for (int y = (int) animal.getY() - 4; y < animal.getY() + 4 && buffCount < 14; ++y) { + for (int z = (int) animal.getZ() - 4; z < animal.getZ() + 4 && buffCount < 14; ++z) { + BlockState state = animal.level().getBlockState(pos.set(x, y, z)); + + if (state.is(BlockTags.WOODEN_FENCES) || state.is(Blocks.HAY_BLOCK)) { + if (animal.getRandom().nextFloat() < 0.3F) + ++progress; + + ++buffCount; + } + } + } + } + } + + return progress; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/CatLieOnBedGoal.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/CatLieOnBedGoal.java new file mode 100644 index 0000000..1236034 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/CatLieOnBedGoal.java @@ -0,0 +1,55 @@ +package net.nuclearteam.createnuclear.content.contraptions.irradiated.cat; + +import net.minecraft.core.BlockPos; +import net.minecraft.tags.BlockTags; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.ai.goal.MoveToBlockGoal; +import net.minecraft.world.level.LevelReader; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.EnumSet; + +@ParametersAreNonnullByDefault +public class CatLieOnBedGoal extends MoveToBlockGoal { + private final IrradiatedCat cat; + + public CatLieOnBedGoal(IrradiatedCat cat, double speedModifier, int searchRange) { + super(cat, speedModifier, searchRange, 6); + this.cat = cat; + this.verticalSearchStart = -2; + this.setFlags(EnumSet.of(Flag.JUMP, Flag.MOVE)); + } + + public boolean canUse() { + return this.cat.isTame() && !this.cat.isOrderedToSit() && !this.cat.isLying() && super.canUse(); + } + + public void start() { + super.start(); + this.cat.setInSittingPose(false); + } + + protected int nextStartTick(PathfinderMob creature) { + return 40; + } + + public void stop() { + super.stop(); + this.cat.setLying(false); + } + + public void tick() { + super.tick(); + this.cat.setInSittingPose(false); + if (!this.isReachedTarget()) { + this.cat.setLying(false); + } else if (!this.cat.isLying()) { + this.cat.setLying(true); + } + + } + + protected boolean isValidTarget(LevelReader level, BlockPos pos) { + return level.isEmptyBlock(pos.above()) && level.getBlockState(pos).is(BlockTags.BEDS); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/CatSitOnBlockGoal.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/CatSitOnBlockGoal.java new file mode 100644 index 0000000..a5fa985 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/CatSitOnBlockGoal.java @@ -0,0 +1,57 @@ +package net.nuclearteam.createnuclear.content.contraptions.irradiated.cat; + +import net.minecraft.core.BlockPos; +import net.minecraft.tags.BlockTags; +import net.minecraft.world.entity.ai.goal.MoveToBlockGoal; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.BedBlock; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.FurnaceBlock; +import net.minecraft.world.level.block.entity.ChestBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BedPart; + +public class CatSitOnBlockGoal extends MoveToBlockGoal { + private final IrradiatedCat cat; + + public CatSitOnBlockGoal(IrradiatedCat cat, double speedModifier) { + super(cat, speedModifier, 8); + this.cat = cat; + } + + public boolean canUse() { + return this.cat.isTame() && !this.cat.isOrderedToSit() && super.canUse(); + } + + public void start() { + super.start(); + this.cat.setInSittingPose(false); + } + + public void stop() { + super.stop(); + this.cat.setInSittingPose(false); + } + + public void tick() { + super.tick(); + this.cat.setInSittingPose(this.isReachedTarget()); + } + + @SuppressWarnings("null") + protected boolean isValidTarget(LevelReader level, BlockPos pos) { + if (!level.isEmptyBlock(pos.above())) { + return false; + } else { + BlockState blockState = level.getBlockState(pos); + if (blockState.is(Blocks.CHEST)) { + return ChestBlockEntity.getOpenCount(level, pos) < 1; + } else { + return blockState.is(Blocks.FURNACE) && blockState.getValue(FurnaceBlock.LIT) || blockState.is(BlockTags.BEDS, (blockStates) -> + blockStates.getOptionalValue(BedBlock.PART) + .map((bedPart) -> bedPart != BedPart.HEAD) + .orElse(true)); + } + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCat.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCat.java index 3472b19..90c5f97 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCat.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCat.java @@ -2,6 +2,7 @@ import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; @@ -9,7 +10,10 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.StructureTags; import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -20,32 +24,51 @@ import net.minecraft.world.entity.ai.goal.*; import net.minecraft.world.entity.ai.goal.target.NonTameRandomTargetGoal; import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.entity.animal.Cat; import net.minecraft.world.entity.animal.Rabbit; import net.minecraft.world.entity.animal.Turtle; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.food.FoodProperties; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.Level; import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.level.block.BedBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.loot.BuiltInLootTables; +import net.minecraft.world.level.storage.loot.LootParams; +import net.minecraft.world.level.storage.loot.LootTable; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.phys.AABB; import net.neoforged.neoforge.event.EventHooks; import net.nuclearteam.createnuclear.CNEntityType; +import net.nuclearteam.createnuclear.CNItems; import net.nuclearteam.createnuclear.CNTags; +import net.nuclearteam.createnuclear.content.contraptions.irradiated.AnimalUtil; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -@SuppressWarnings({"unused"}) +@SuppressWarnings({"unused", "deprecation"}) public class IrradiatedCat extends TamableAnimal { public static final double TEMPT_SPEED_MOD = 0.6; public static final double WALK_SPEED_MOD = 0.8; public static final double SPRINT_SPEED_MOD = 1.33; + private static final Ingredient TEMPT_INGREDIENT; private static final EntityDataAccessor IS_LYING; private static final EntityDataAccessor RELAX_STATE_ONE; - @Nullable - private IrradiatedCatAvoidEntityGoal avoidPlayersGoal; + private CatAvoidEntityGoal avoidPlayersGoal; @Nullable private TemptGoal temptGoal; private float lieDownAmount; @@ -57,24 +80,25 @@ public class IrradiatedCat extends TamableAnimal { public IrradiatedCat(EntityType entityType, Level level) { super(entityType, level); - this.reassessTameGoals(); } + @SuppressWarnings({ "rawtypes", "unchecked" }) protected void registerGoals() { - this.temptGoal = new IrradiatedCatTemptGoal(this, 0.6, (p_335255_) -> p_335255_.is(CNTags.CNItemTags.FUEL.tag), true); + this.temptGoal = new CatTemptGoal(this, 0.6, TEMPT_INGREDIENT, true); this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(1, new PanicGoal(this, 1.5)); this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); - this.goalSelector.addGoal(3, new IrradiatedCatRelaxOnOwnerGoal(this)); + this.goalSelector.addGoal(3, new CatRelaxOnOwnerGoal(this)); this.goalSelector.addGoal(4, this.temptGoal); - this.goalSelector.addGoal(5, new IrradiatedCatLieOnBedGoal(this, 1.1, 8)); - this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0F, 10.0F, 5.0F)); - this.goalSelector.addGoal(7, new IrradiatedCatSitOnBlockGoal(this, 0.8)); + this.goalSelector.addGoal(5, new CatLieOnBedGoal(this, 1.1, 8)); + this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0, 10.0F, 5.0F)); + this.goalSelector.addGoal(7, new CatSitOnBlockGoal(this, 0.8)); this.goalSelector.addGoal(8, new LeapAtTargetGoal(this, 0.3F)); this.goalSelector.addGoal(9, new OcelotAttackGoal(this)); this.goalSelector.addGoal(10, new BreedGoal(this, 0.8)); this.goalSelector.addGoal(11, new WaterAvoidingRandomStrollGoal(this, 0.8, 1.0000001E-5F)); this.goalSelector.addGoal(12, new LookAtPlayerGoal(this, Player.class, 10.0F)); - this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, null)); + this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, (Predicate)null)); this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR)); } @@ -86,16 +110,14 @@ public boolean isLying() { return this.entityData.get(IS_LYING); } - void setRelaxStateOne(boolean relaxStateOne) { + public void setRelaxStateOne(boolean relaxStateOne) { this.entityData.set(RELAX_STATE_ONE, relaxStateOne); } - boolean isRelaxStateOne() { + public boolean isRelaxStateOne() { return this.entityData.get(RELAX_STATE_ONE); } - - protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); builder.define(IS_LYING, false); @@ -112,11 +134,11 @@ public void readAdditionalSaveData(CompoundTag compound) { public void customServerAiStep() { if (this.getMoveControl().hasWanted()) { - double d0 = this.getMoveControl().getSpeedModifier(); - if (d0 == 0.6) { + double d = this.getMoveControl().getSpeedModifier(); + if (d == 0.6) { this.setPose(Pose.CROUCHING); this.setSprinting(false); - } else if (d0 == 1.33) { + } else if (d == 1.33) { this.setPose(Pose.STANDING); this.setSprinting(true); } else { @@ -148,7 +170,7 @@ public int getAmbientSoundInterval() { } public void hiss() { - this.makeSound(SoundEvents.CAT_HISS); + this.playSound(SoundEvents.CAT_HISS, this.getSoundVolume(), this.getVoicePitch()); } protected SoundEvent getHurtSound(DamageSource damageSource) { @@ -160,10 +182,7 @@ protected SoundEvent getDeathSound() { } public static AttributeSupplier.Builder createAttributes() { - return Mob.createMobAttributes() - .add(Attributes.MAX_HEALTH, 10.0F) - .add(Attributes.MOVEMENT_SPEED, 0.3F) - .add(Attributes.ATTACK_DAMAGE, 3.0F); + return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896).add(Attributes.ATTACK_DAMAGE, 3.0); } protected void usePlayerItem(Player player, InteractionHand hand, ItemStack stack) { @@ -174,6 +193,14 @@ protected void usePlayerItem(Player player, InteractionHand hand, ItemStack stac super.usePlayerItem(player, hand, stack); } + private float getAttackDamage() { + return (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE); + } + + public boolean doHurtTarget(Entity target) { + return target.hurt(this.damageSources().mobAttack(this), this.getAttackDamage()); + } + public void tick() { super.tick(); if (this.temptGoal != null && this.temptGoal.isRunning() && !this.isTame() && this.tickCount % 100 == 0) { @@ -228,91 +255,98 @@ public float getRelaxStateOneAmount(float partialTicks) { } @Nullable - public IrradiatedCat getBreedOffspring(ServerLevel level, AgeableMob otherParent) { - return CNEntityType.IRRADIATED_CAT.create(level); + @Override + public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob otherParent) { + Cat cat = EntityType.CAT.create(level); + if (cat != null && otherParent instanceof Cat cat2) { + + if (this.isTame()) { + cat.setOwnerUUID(this.getOwnerUUID()); + cat.setTame(true, false); + } + } + + return cat; } public boolean canMate(Animal otherAnimal) { if (!this.isTame()) { return false; + } else if (!(otherAnimal instanceof Cat)) { + return false; } else { - boolean var10000; - if (otherAnimal instanceof IrradiatedCat irradiatedCat) { - var10000 = irradiatedCat.isTame() && super.canMate(otherAnimal); - } else { - var10000 = false; - } - - return var10000; + Cat cat = (Cat)otherAnimal; + return cat.isTame() && super.canMate(otherAnimal); } } - public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnType, @Nullable SpawnGroupData spawnGroupData) { - spawnGroupData = super.finalizeSpawn(level, difficulty, spawnType, spawnGroupData); - boolean flag = level.getMoonBrightness() > 0.9F; - ServerLevel serverlevel = level.getLevel(); - + @SuppressWarnings("null") + public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag) { + spawnData = super.finalizeSpawn(level, difficulty, reason, spawnData); + boolean bl = level.getMoonBrightness() > 0.9F; + ServerLevel serverLevel = level.getLevel(); + if (serverLevel.structureManager().getStructureWithPieceAt(this.blockPosition(), StructureTags.CATS_SPAWN_AS_BLACK).isValid()) { + this.setPersistenceRequired(); + } - return spawnGroupData; + return spawnData; } + @SuppressWarnings("null") public InteractionResult mobInteract(Player player, InteractionHand hand) { - ItemStack itemstack = player.getItemInHand(hand); - Item item = itemstack.getItem(); - if (this.isTame()) { - if (this.isOwnedBy(player)) { - if (this.isFood(itemstack) && this.getHealth() < this.getMaxHealth()) { - if (!this.level().isClientSide()) { - FoodProperties foodproperties = itemstack.getFoodProperties(this); - this.heal(foodproperties != null ? (float)foodproperties.nutrition() : 1.0F); - this.usePlayerItem(player, hand, itemstack); + ItemStack itemStack = player.getItemInHand(hand); + Item item = itemStack.getItem(); + if (this.level().isClientSide) { + if (this.isTame() && this.isOwnedBy(player)) { + return InteractionResult.SUCCESS; + } else { + return !this.isFood(itemStack) || !(this.getHealth() < this.getMaxHealth()) && this.isTame() ? InteractionResult.PASS : InteractionResult.SUCCESS; + } + } else { + InteractionResult interactionResult; + if (this.isTame()) { + if (this.isOwnedBy(player)) { + if (this.isFood(itemStack) && this.getHealth() < this.getMaxHealth()) { + this.usePlayerItem(player, hand, itemStack); + this.heal((float)item.getFoodProperties(new ItemStack(item), null).saturation()); + return InteractionResult.CONSUME; } - return InteractionResult.sidedSuccess(this.level().isClientSide()); - } + interactionResult = super.mobInteract(player, hand); + if (!interactionResult.consumesAction() || this.isBaby()) { + this.setOrderedToSit(!this.isOrderedToSit()); + } - InteractionResult interactionresult = super.mobInteract(player, hand); - if (!interactionresult.consumesAction()) { - this.setOrderedToSit(!this.isOrderedToSit()); - return InteractionResult.sidedSuccess(this.level().isClientSide()); + return interactionResult; } - - return interactionresult; + } else if (itemStack.is(CNItems.YELLOWCAKE.get())) { + return AnimalUtil.blockTamingWip(player, this.level()); } - } else if (this.isFood(itemstack)) { - if (!this.level().isClientSide()) { - this.usePlayerItem(player, hand, itemstack); - this.tryToTame(player); + + interactionResult = super.mobInteract(player, hand); + if (interactionResult.consumesAction()) { this.setPersistenceRequired(); } - return InteractionResult.sidedSuccess(this.level().isClientSide()); + return interactionResult; } - - InteractionResult interactionresult1 = super.mobInteract(player, hand); - if (interactionresult1.consumesAction()) { - this.setPersistenceRequired(); - } - - return interactionresult1; } public boolean isFood(ItemStack stack) { - return stack.is(CNTags.CNItemTags.FUEL.tag); + return TEMPT_INGREDIENT.test(stack); } - public boolean removeWhenFarAway(double distanceToClosestPlayer) { - return !this.isTame() && this.tickCount > 2400; + protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { + return dimensions.height() * 0.5F; } - public void setTame(boolean tame, boolean applyTamingSideEffects) { - super.setTame(tame, applyTamingSideEffects); - this.reassessTameGoals(); + public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return !this.isTame() && this.tickCount > 2400; } protected void reassessTameGoals() { if (this.avoidPlayersGoal == null) { - this.avoidPlayersGoal = new IrradiatedCatAvoidEntityGoal<>(this, Player.class, 16.0F, 0.8, 1.33); + this.avoidPlayersGoal = new CatAvoidEntityGoal<>(this, Player.class, 16.0F, 0.8, 1.33); } this.goalSelector.removeGoal(this.avoidPlayersGoal); @@ -322,23 +356,183 @@ protected void reassessTameGoals() { } - private void tryToTame(Player player) { - if (this.random.nextInt(3) == 0 && !EventHooks.onAnimalTame(this, player)) { - this.tame(player); - this.setOrderedToSit(true); - this.level().broadcastEntityEvent(this, (byte)7); - } else { - this.level().broadcastEntityEvent(this, (byte)6); - } - - } - public boolean isSteppingCarefully() { return this.isCrouching() || super.isSteppingCarefully(); } static { + TEMPT_INGREDIENT = Ingredient.of(CNItems.YELLOWCAKE); IS_LYING = SynchedEntityData.defineId(IrradiatedCat.class, EntityDataSerializers.BOOLEAN); RELAX_STATE_ONE = SynchedEntityData.defineId(IrradiatedCat.class, EntityDataSerializers.BOOLEAN); } + + + static class CatRelaxOnOwnerGoal extends Goal { + private final IrradiatedCat cat; + @Nullable + private Player ownerPlayer; + @Nullable + private BlockPos goalPos; + private int onBedTicks; + + public CatRelaxOnOwnerGoal(IrradiatedCat cat) { + this.cat = cat; + } + + public boolean canUse() { + if (!this.cat.isTame()) { + return false; + } else if (this.cat.isOrderedToSit()) { + return false; + } else { + LivingEntity livingEntity = this.cat.getOwner(); + if (livingEntity instanceof Player) { + this.ownerPlayer = (Player)livingEntity; + if (!livingEntity.isSleeping()) { + return false; + } + + if (this.cat.distanceToSqr(this.ownerPlayer) > 100.0) { + return false; + } + + BlockPos blockPos = this.ownerPlayer.blockPosition(); + BlockState blockState = this.cat.level().getBlockState(blockPos); + if (blockState.is(BlockTags.BEDS)) { + this.goalPos = blockState.getOptionalValue(BedBlock.FACING).map((direction) -> blockPos.relative(direction.getOpposite())).orElseGet(() -> new BlockPos(blockPos)); + return !this.spaceIsOccupied(); + } + } + + return false; + } + } + + private boolean spaceIsOccupied() { + assert this.goalPos != null; + List list = this.cat.level().getEntitiesOfClass(IrradiatedCat.class, (new AABB(this.goalPos)).inflate(2.0)); + Iterator var2 = list.iterator(); + + IrradiatedCat cat; + do { + do { + if (!var2.hasNext()) { + return false; + } + + cat = var2.next(); + } while(cat == this.cat); + } while(!cat.isLying() && !cat.isRelaxStateOne()); + + return true; + } + + public boolean canContinueToUse() { + return this.cat.isTame() && !this.cat.isOrderedToSit() && this.ownerPlayer != null && this.ownerPlayer.isSleeping() && this.goalPos != null && !this.spaceIsOccupied(); + } + + public void start() { + if (this.goalPos != null) { + this.cat.setInSittingPose(false); + this.cat.getNavigation().moveTo(this.goalPos.getX(), this.goalPos.getY(), this.goalPos.getZ(), 1.100000023841858); + } + + } + + public void stop() { + this.cat.setLying(false); + float f = this.cat.level().getTimeOfDay(1.0F); + if (this.ownerPlayer.getSleepTimer() >= 100 && (double)f > 0.77 && (double)f < 0.8 && (double)this.cat.level().getRandom().nextFloat() < 0.7) { + this.giveMorningGift(); + } + + this.onBedTicks = 0; + this.cat.setRelaxStateOne(false); + this.cat.getNavigation().stop(); + } + + private void giveMorningGift() { + RandomSource randomSource = this.cat.getRandom(); + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + mutableBlockPos.set(this.cat.isLeashed() ? this.cat.getLeashHolder().blockPosition() : this.cat.blockPosition()); + this.cat.randomTeleport(mutableBlockPos.getX() + randomSource.nextInt(11) - 5, mutableBlockPos.getY() + randomSource.nextInt(5) - 2, (double)(mutableBlockPos.getZ() + randomSource.nextInt(11) - 5), false); + mutableBlockPos.set(this.cat.blockPosition()); + LootTable lootTable = this.cat.level().getServer().reloadableRegistries().getLootTable(BuiltInLootTables.CAT_MORNING_GIFT); + LootParams lootParams = (new LootParams.Builder((ServerLevel)this.cat.level())).withParameter(LootContextParams.ORIGIN, this.cat.position()).withParameter(LootContextParams.THIS_ENTITY, this.cat).create(LootContextParamSets.GIFT); + List list = lootTable.getRandomItems(lootParams); + + for (ItemStack itemStack : list) { + this.cat.level().addFreshEntity(new ItemEntity(this.cat.level(), (double) mutableBlockPos.getX() - (double) Mth.sin(this.cat.yBodyRot * 0.017453292F), (double) mutableBlockPos.getY(), (double) mutableBlockPos.getZ() + (double) Mth.cos(this.cat.yBodyRot * 0.017453292F), itemStack)); + } + + } + + public void tick() { + if (this.ownerPlayer != null && this.goalPos != null) { + this.cat.setInSittingPose(false); + this.cat.getNavigation().moveTo(this.goalPos.getX(), this.goalPos.getY(), this.goalPos.getZ(), 1.100000023841858); + if (this.cat.distanceToSqr(this.ownerPlayer) < 2.5) { + ++this.onBedTicks; + if (this.onBedTicks > this.adjustedTickDelay(16)) { + this.cat.setLying(true); + this.cat.setRelaxStateOne(false); + } else { + this.cat.lookAt(this.ownerPlayer, 45.0F, 45.0F); + this.cat.setRelaxStateOne(true); + } + } else { + this.cat.setLying(false); + } + } + + } + } + + private static class CatTemptGoal extends TemptGoal { + @Nullable + private Player selectedPlayer; + private final IrradiatedCat cat; + + public CatTemptGoal(IrradiatedCat cat, double speedModifier, Ingredient items, boolean canScare) { + super(cat, speedModifier, items, canScare); + this.cat = cat; + } + + public void tick() { + super.tick(); + if (this.selectedPlayer == null && this.mob.getRandom().nextInt(this.adjustedTickDelay(600)) == 0) { + this.selectedPlayer = this.player; + } else if (this.mob.getRandom().nextInt(this.adjustedTickDelay(500)) == 0) { + this.selectedPlayer = null; + } + + } + + protected boolean canScare() { + return this.selectedPlayer != null && this.selectedPlayer.equals(this.player) ? false : super.canScare(); + } + + public boolean canUse() { + return super.canUse() && !this.cat.isTame(); + } + } + + static class CatAvoidEntityGoal extends AvoidEntityGoal { + private final IrradiatedCat cat; + + public CatAvoidEntityGoal(IrradiatedCat cat, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double sprintSpeedModifier) { + super(cat, entityClassToAvoid, maxDist, walkSpeedModifier, sprintSpeedModifier); + Predicate var10006 = EntitySelector.NO_CREATIVE_OR_SPECTATOR; + Objects.requireNonNull(var10006); + this.cat = cat; + } + + public boolean canUse() { + return !this.cat.isTame() && super.canUse(); + } + + public boolean canContinueToUse() { + return !this.cat.isTame() && super.canContinueToUse(); + } + } } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatAvoidEntityGoal.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatAvoidEntityGoal.java deleted file mode 100644 index 9d2e9e8..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatAvoidEntityGoal.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.nuclearteam.createnuclear.content.contraptions.irradiated.cat; - -import net.minecraft.world.entity.EntitySelector; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; - -public class IrradiatedCatAvoidEntityGoal extends AvoidEntityGoal { - private final IrradiatedCat irradiatedCat; - - public IrradiatedCatAvoidEntityGoal(IrradiatedCat cat, Class entityClassToAvoid, float maxDist, double walkSpeedModifier, double sprintSpeedModifier) { - super(cat, entityClassToAvoid, maxDist, walkSpeedModifier, sprintSpeedModifier, EntitySelector.NO_CREATIVE_OR_SPECTATOR::test); - this.irradiatedCat = cat; - } - - public boolean canUse() { - return !this.irradiatedCat.isTame() && super.canUse(); - } - - public boolean canContinueToUse() { - return !this.irradiatedCat.isTame() && super.canContinueToUse(); - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatLieOnBedGoal.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatLieOnBedGoal.java deleted file mode 100644 index 1c584a7..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatLieOnBedGoal.java +++ /dev/null @@ -1,55 +0,0 @@ -package net.nuclearteam.createnuclear.content.contraptions.irradiated.cat; - -import net.minecraft.core.BlockPos; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.entity.PathfinderMob; -import net.minecraft.world.entity.ai.goal.MoveToBlockGoal; -import net.minecraft.world.level.LevelReader; - -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.EnumSet; - -@ParametersAreNonnullByDefault -public class IrradiatedCatLieOnBedGoal extends MoveToBlockGoal { - private final IrradiatedCat irradiatedCat; - - public IrradiatedCatLieOnBedGoal(IrradiatedCat cat, double speedModifier, int searchRange) { - super(cat, speedModifier, searchRange, 6); - this.irradiatedCat = cat; - this.verticalSearchStart = -2; - this.setFlags(EnumSet.of(Flag.JUMP, Flag.MOVE)); - } - - public boolean canUse() { - return this.irradiatedCat.isTame() && !this.irradiatedCat.isOrderedToSit() && !this.irradiatedCat.isLying() && super.canUse(); - } - - public void start() { - super.start(); - this.irradiatedCat.setInSittingPose(false); - } - - protected int nextStartTick(PathfinderMob creature) { - return 40; - } - - public void stop() { - super.stop(); - this.irradiatedCat.setLying(false); - } - - public void tick() { - super.tick(); - this.irradiatedCat.setInSittingPose(false); - if (!this.isReachedTarget()) { - this.irradiatedCat.setLying(false); - } else if (!this.irradiatedCat.isLying()) { - this.irradiatedCat.setLying(true); - } - - } - - protected boolean isValidTarget(LevelReader level, BlockPos pos) { - return level.isEmptyBlock(pos.above()) && level.getBlockState(pos).is(BlockTags.BEDS); - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatRelaxOnOwnerGoal.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatRelaxOnOwnerGoal.java deleted file mode 100644 index 1b6dbbc..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatRelaxOnOwnerGoal.java +++ /dev/null @@ -1,135 +0,0 @@ -package net.nuclearteam.createnuclear.content.contraptions.irradiated.cat; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.ai.goal.Goal; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.storage.loot.BuiltInLootTables; -import net.minecraft.world.level.storage.loot.LootParams; -import net.minecraft.world.level.storage.loot.LootTable; -import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.phys.AABB; - -import javax.annotation.Nullable; - -@SuppressWarnings({"unused"}) -public class IrradiatedCatRelaxOnOwnerGoal extends Goal { - private final IrradiatedCat irradiatedCat; - @Nullable - private Player ownerPlayer; - @Nullable - private BlockPos goalPos; - private int onBedTicks; - - public IrradiatedCatRelaxOnOwnerGoal(IrradiatedCat cat) { - this.irradiatedCat = cat; - } - - public boolean canUse() { - if (!this.irradiatedCat.isTame()) { - return false; - } else if (this.irradiatedCat.isOrderedToSit()) { - return false; - } else { - LivingEntity livingentity = this.irradiatedCat.getOwner(); - if (livingentity instanceof Player) { - this.ownerPlayer = (Player)livingentity; - if (!livingentity.isSleeping()) { - return false; - } - - if (this.irradiatedCat.distanceToSqr(this.ownerPlayer) > (double)100.0F) { - return false; - } - - BlockPos blockpos = this.ownerPlayer.blockPosition(); - BlockState blockstate = this.irradiatedCat.level().getBlockState(blockpos); - } - - return false; - } - } - - private boolean spaceIsOccupied() { - BlockPos pos = this.goalPos; - if (pos == null) { - - return false; - } - - AABB searchArea = new AABB(pos).inflate(2.0); - for (IrradiatedCat nearbyCat : this.irradiatedCat.level().getEntitiesOfClass(IrradiatedCat.class, searchArea)) { - if (nearbyCat != this.irradiatedCat && (nearbyCat.isLying() || nearbyCat.isRelaxStateOne())) { - return true; - } - } - - return false; - } - - public boolean canContinueToUse() { - return this.irradiatedCat.isTame() && !this.irradiatedCat.isOrderedToSit() && this.ownerPlayer != null && this.ownerPlayer.isSleeping() && this.goalPos != null && !this.spaceIsOccupied(); - } - - public void start() { - if (this.goalPos != null) { - this.irradiatedCat.setInSittingPose(false); - this.irradiatedCat.getNavigation().moveTo(this.goalPos.getX(), this.goalPos.getY(), this.goalPos.getZ(), 1.1F); - } - - } - - public void stop() { - this.irradiatedCat.setLying(false); - float f = this.irradiatedCat.level().getTimeOfDay(1.0F); - if (this.ownerPlayer.getSleepTimer() >= 100 && (double)f > 0.77 && (double)f < 0.8 && (double)this.irradiatedCat.level().getRandom().nextFloat() < 0.7) { - this.giveMorningGift(); - } - - this.onBedTicks = 0; - this.irradiatedCat.setRelaxStateOne(false); - this.irradiatedCat.getNavigation().stop(); - } - - private void giveMorningGift() { - RandomSource randomsource = this.irradiatedCat.getRandom(); - BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(); - blockpos$mutableblockpos.set(this.irradiatedCat.isLeashed() ? this.irradiatedCat.getLeashHolder().blockPosition() : this.irradiatedCat.blockPosition()); - this.irradiatedCat.randomTeleport(blockpos$mutableblockpos.getX() + randomsource.nextInt(11) - 5, blockpos$mutableblockpos.getY() + randomsource.nextInt(5) - 2, blockpos$mutableblockpos.getZ() + randomsource.nextInt(11) - 5, false); - blockpos$mutableblockpos.set(this.irradiatedCat.blockPosition()); - LootTable loottable = this.irradiatedCat.level().getServer().reloadableRegistries().getLootTable(BuiltInLootTables.CAT_MORNING_GIFT); - LootParams lootparams = (new LootParams.Builder((ServerLevel)this.irradiatedCat.level())).withParameter(LootContextParams.ORIGIN, this.irradiatedCat.position()).withParameter(LootContextParams.THIS_ENTITY, this.irradiatedCat).create(LootContextParamSets.GIFT); - - for (ItemStack itemstack : loottable.getRandomItems(lootparams)) { - this.irradiatedCat.level().addFreshEntity(new ItemEntity(this.irradiatedCat.level(), (double) blockpos$mutableblockpos.getX() - (double) Mth.sin(this.irradiatedCat.yBodyRot * ((float) Math.PI / 180F)), blockpos$mutableblockpos.getY(), (double) blockpos$mutableblockpos.getZ() + (double) Mth.cos(this.irradiatedCat.yBodyRot * ((float) Math.PI / 180F)), itemstack)); - } - - } - - public void tick() { - if (this.ownerPlayer != null && this.goalPos != null) { - this.irradiatedCat.setInSittingPose(false); - this.irradiatedCat.getNavigation().moveTo(this.goalPos.getX(), this.goalPos.getY(), this.goalPos.getZ(), 1.1F); - if (this.irradiatedCat.distanceToSqr(this.ownerPlayer) < (double)2.5F) { - ++this.onBedTicks; - if (this.onBedTicks > this.adjustedTickDelay(16)) { - this.irradiatedCat.setLying(true); - this.irradiatedCat.setRelaxStateOne(false); - } else { - this.irradiatedCat.lookAt(this.ownerPlayer, 45.0F, 45.0F); - this.irradiatedCat.setRelaxStateOne(true); - } - } else { - this.irradiatedCat.setLying(false); - } - } - - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatSitOnBlockGoal.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatSitOnBlockGoal.java deleted file mode 100644 index 2d0e460..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatSitOnBlockGoal.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.nuclearteam.createnuclear.content.contraptions.irradiated.cat; - -import net.minecraft.core.BlockPos; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.entity.ai.goal.MoveToBlockGoal; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.BedBlock; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.FurnaceBlock; -import net.minecraft.world.level.block.entity.ChestBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BedPart; - -public class IrradiatedCatSitOnBlockGoal extends MoveToBlockGoal { - private final IrradiatedCat irradiatedCat; - - public IrradiatedCatSitOnBlockGoal(IrradiatedCat cat, double speedModifier) { - super(cat, speedModifier, 8); - this.irradiatedCat = cat; - } - - public boolean canUse() { - return this.irradiatedCat.isTame() && !this.irradiatedCat.isOrderedToSit() && super.canUse(); - } - - public void start() { - super.start(); - this.irradiatedCat.setInSittingPose(false); - } - - public void stop() { - super.stop(); - this.irradiatedCat.setInSittingPose(false); - } - - public void tick() { - super.tick(); - this.irradiatedCat.setInSittingPose(this.isReachedTarget()); - } - - protected boolean isValidTarget(LevelReader level, BlockPos pos) { - if (!level.isEmptyBlock(pos.above())) { - return false; - } else { - BlockState blockstate = level.getBlockState(pos); - if (blockstate.is(Blocks.CHEST)) { - return ChestBlockEntity.getOpenCount(level, pos) < 1; - } else { - return blockstate.is(Blocks.FURNACE) && (Boolean) blockstate.getValue(FurnaceBlock.LIT) || blockstate.is(BlockTags.BEDS, (p_25156_) -> (Boolean) p_25156_.getOptionalValue(BedBlock.PART).map((p_148084_) -> p_148084_ != BedPart.HEAD).orElse(true)); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatTemptGoal.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatTemptGoal.java deleted file mode 100644 index eb4044a..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cat/IrradiatedCatTemptGoal.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.nuclearteam.createnuclear.content.contraptions.irradiated.cat; - -import net.minecraft.world.entity.ai.goal.TemptGoal; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; - -import javax.annotation.Nullable; -import java.util.function.Predicate; - -public class IrradiatedCatTemptGoal extends TemptGoal { - @Nullable - private Player selectedPlayer; - private final IrradiatedCat irradiatedCat; - - public IrradiatedCatTemptGoal(IrradiatedCat cat, double speedModifier, Predicate items, boolean canScare) { - super(cat, speedModifier, items, canScare); - this.irradiatedCat = cat; - } - - public void tick() { - super.tick(); - if (this.selectedPlayer == null && this.mob.getRandom().nextInt(this.adjustedTickDelay(600)) == 0) { - this.selectedPlayer = this.player; - } else if (this.mob.getRandom().nextInt(this.adjustedTickDelay(500)) == 0) { - this.selectedPlayer = null; - } - - } - - protected boolean canScare() { - return (this.selectedPlayer == null || !this.selectedPlayer.equals(this.player)) && super.canScare(); - } - - public boolean canUse() { - return super.canUse() && !this.irradiatedCat.isTame(); - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/chicken/IrradiatedChicken.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/chicken/IrradiatedChicken.java index 9ddde01..2d700e0 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/chicken/IrradiatedChicken.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/chicken/IrradiatedChicken.java @@ -3,6 +3,10 @@ import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; @@ -13,14 +17,18 @@ import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.goal.*; import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.entity.animal.Chicken; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.pathfinder.PathType; import net.minecraft.world.phys.Vec3; import net.nuclearteam.createnuclear.CNEntityType; import net.nuclearteam.createnuclear.CNTags; +import net.nuclearteam.createnuclear.content.contraptions.irradiated.IrradiatedAnimal; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @@ -28,20 +36,30 @@ @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault @SuppressWarnings("unused") -public class IrradiatedChicken extends Animal { +public class IrradiatedChicken extends Animal implements IrradiatedAnimal { private static final EntityDimensions BABY_DIMENSIONS; + private static final EntityDataAccessor DATA_CONVERTING_ID = SynchedEntityData.defineId(IrradiatedChicken.class, EntityDataSerializers.BOOLEAN); public float flap; public float flapSpeed; public float oFlapSpeed; public float oFlap; public float flapping = 1.0F; private float nextFlap = 1.0F; + public int eggTime; + public boolean isChickenJockey; + private int conversionTime; public IrradiatedChicken(EntityType entityType, Level level) { super(entityType, level); + this.eggTime = this.random.nextInt(6000) + 6000; this.setPathfindingMalus(PathType.WATER, 0.0F); } + protected void defineSynchedData(SynchedEntityData.Builder builder) { + super.defineSynchedData(builder); + builder.define(DATA_CONVERTING_ID, false); + } + protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); this.goalSelector.addGoal(1, new PanicGoal(this, 1.4)); @@ -80,6 +98,13 @@ public void aiStep() { } this.flap += this.flapping * 2.0F; + if (!this.level().isClientSide && this.isAlive() && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) { + this.playSound(SoundEvents.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + this.spawnAtLocation(Items.EGG); + this.gameEvent(GameEvent.ENTITY_PLACE); + this.eggTime = this.random.nextInt(6000) + 6000; + } + } protected boolean isFlapping() { @@ -115,13 +140,31 @@ public boolean isFood(ItemStack stack) { return stack.is(CNTags.CNItemTags.FUEL.tag); } + protected int getBaseExperienceReward() { + return this.isChickenJockey() ? 10 : super.getBaseExperienceReward(); + } public void readAdditionalSaveData(CompoundTag compound) { super.readAdditionalSaveData(compound); + this.isChickenJockey = compound.getBoolean("IsChickenJockey"); + if (compound.contains("EggLayTime")) { + this.eggTime = compound.getInt("EggLayTime"); + } + + if (compound.contains("ConversionTime", Tag.TAG_ANY_NUMERIC) && compound.getInt("ConversionTime") > -1) { + this.startConverting(compound.getInt("ConversionTime")); + } } public void addAdditionalSaveData(CompoundTag compound) { super.addAdditionalSaveData(compound); + compound.putBoolean("IsChickenJockey", this.isChickenJockey); + compound.putInt("EggLayTime", this.eggTime); + compound.putInt("ConversionTime", this.isConverting() ? this.conversionTime : -1); + } + + public boolean removeWhenFarAway(double distanceToClosestPlayer) { + return this.isChickenJockey(); } protected void positionRider(Entity passenger, Entity.MoveFunction callback) { @@ -132,6 +175,53 @@ protected void positionRider(Entity passenger, Entity.MoveFunction callback) { } + public boolean isChickenJockey() { + return this.isChickenJockey; + } + + public void setChickenJockey(boolean isChickenJockey) { + this.isChickenJockey = isChickenJockey; + } + + @Override + public EntityType getNormalVariant() { + return EntityType.CHICKEN; + } + + @Override + public void readFromVanilla(Animal animal) { + if (animal instanceof Chicken chicken) { + this.setChickenJockey(chicken.isChickenJockey()); + } + } + + @Override + public void writeToVanilla(Animal animal) { + if (animal instanceof Chicken chicken) { + chicken.setChickenJockey(this.isChickenJockey()); + } + } + + @Override + public boolean isConverting() { + return this.entityData.get(DATA_CONVERTING_ID); + } + + @Override + public void setConverting() { + this.entityData.set(DATA_CONVERTING_ID, true); + } + + @Override + public void setConversionTime(int conversionTime) { + this.conversionTime = conversionTime; + } + + @Override + public int getConversionTime() { + return this.conversionTime; + } + static { BABY_DIMENSIONS = CNEntityType.IRRADIATED_CHICKEN.get().getDimensions().scale(0.5F).withEyeHeight(0.2975F); } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cow/IrradiatedCow.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cow/IrradiatedCow.java new file mode 100644 index 0000000..bc5599c --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cow/IrradiatedCow.java @@ -0,0 +1,100 @@ +package net.nuclearteam.createnuclear.content.contraptions.irradiated.cow; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.*; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.goal.*; +import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemUtils; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.nuclearteam.createnuclear.CNEntityType; +import net.nuclearteam.createnuclear.CNItems; +import net.nuclearteam.createnuclear.content.contraptions.irradiated.AnimalUtil; + +import javax.annotation.Nullable; + +public class IrradiatedCow extends Animal { + public IrradiatedCow(EntityType pEntityType, Level pLevel) { + super(pEntityType, pLevel); + } + + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new PanicGoal(this, 2.0D)); + this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, Ingredient.of(Items.WHEAT), false)); + this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25D)); + this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); + } + + // Define the base food of the animal (e.g., Wheat for Cows) + private static final Ingredient FOOD_ITEMS = Ingredient.of(CNItems.YELLOWCAKE); + + @Override + public boolean isFood(ItemStack stack) { + // Check if the stack is a valid Yellowcake or the base food + return AnimalUtil.isFood(stack, FOOD_ITEMS); + } + + public static AttributeSupplier.Builder createAttributes() { + return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, (double)0.2F); + } + + protected SoundEvent getAmbientSound() { + return SoundEvents.COW_AMBIENT; + } + + protected SoundEvent getHurtSound(DamageSource pDamageSource) { + return SoundEvents.COW_HURT; + } + + protected SoundEvent getDeathSound() { + return SoundEvents.COW_DEATH; + } + + protected void playStepSound(BlockPos pPos, BlockState pBlock) { + this.playSound(SoundEvents.COW_STEP, 0.15F, 1.0F); + } + + /** + * Returns the volume for the sounds this mob makes. + */ + protected float getSoundVolume() { + return 0.4F; + } + + public InteractionResult mobInteract(Player pPlayer, InteractionHand pHand) { + ItemStack itemstack = pPlayer.getItemInHand(pHand); + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { + pPlayer.playSound(SoundEvents.COW_MILK, 1.0F, 1.0F); + ItemStack itemstack1 = ItemUtils.createFilledResult(itemstack, pPlayer, Items.MILK_BUCKET.getDefaultInstance()); + pPlayer.setItemInHand(pHand, itemstack1); + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { + return super.mobInteract(pPlayer, pHand); + } + } + + @Nullable + public IrradiatedCow getBreedOffspring(ServerLevel pLevel, AgeableMob pOtherParent) { + return CNEntityType.IRRADIATED_COW.create(pLevel); + } + + protected float getStandingEyeHeight(Pose pPose, EntityDimensions pSize) { + return this.isBaby() ? pSize.height() * 0.95F : 1.3F; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cow/IrradiatedCowModel.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cow/IrradiatedCowModel.java new file mode 100644 index 0000000..da97720 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cow/IrradiatedCowModel.java @@ -0,0 +1,103 @@ +package net.nuclearteam.createnuclear.content.contraptions.irradiated.cow; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.model.AgeableListModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.*; +import net.minecraft.util.Mth; + +public class IrradiatedCowModel extends AgeableListModel { + // This layer location should be baked with EntityRendererProvider.Context in the entity renderer and passed into this model's constructor + private final ModelPart head; + private final ModelPart pustule; + private final ModelPart body; + private final ModelPart pustule3; + private final ModelPart legs; + private final ModelPart leg1; + private final ModelPart leg2; + private final ModelPart leg3; + private final ModelPart leg4; + private final ModelPart pustule2; + + public IrradiatedCowModel(ModelPart root) { + this.head = root.getChild("head"); + this.pustule = this.head.getChild("pustule"); + this.body = root.getChild("body"); + this.pustule3 = this.body.getChild("pustule3"); + this.legs = root.getChild("legs"); + this.leg1 = this.legs.getChild("leg1"); + this.leg2 = this.legs.getChild("leg2"); + this.leg3 = this.legs.getChild("leg3"); + this.leg4 = this.legs.getChild("leg4"); + this.pustule2 = this.leg4.getChild("pustule2"); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + PartDefinition head = partdefinition.addOrReplaceChild("head", CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -4.0F, -6.0F, 8.0F, 8.0F, 6.0F, new CubeDeformation(0.0F)) + .texOffs(22, 0).addBox(4.0F, -5.0F, -4.0F, 1.0F, 3.0F, 1.0F, new CubeDeformation(0.0F)) + .texOffs(22, 0).addBox(-5.0F, -5.0F, -4.0F, 1.0F, 3.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, 4.0F, -8.0F)); + + PartDefinition pustule = head.addOrReplaceChild("pustule", CubeListBuilder.create(), PartPose.offset(0.0F, 0.0F, 0.0F)); + + PartDefinition pustule_head_r1 = pustule.addOrReplaceChild("pustule_head_r1", CubeListBuilder.create().texOffs(54, 9).addBox(-1.1F, -0.8F, -0.6F, 2.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(3.4F, -4.0F, -1.0F, -0.2739F, 0.2947F, -0.0814F)); + + PartDefinition body = partdefinition.addOrReplaceChild("body", CubeListBuilder.create().texOffs(18, 4).addBox(-6.0F, -10.0F, -7.0F, 12.0F, 18.0F, 10.0F, new CubeDeformation(0.0F)) + .texOffs(52, 0).addBox(-2.0F, 2.0F, -8.0F, 4.0F, 6.0F, 1.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 5.0F, 2.0F, 1.5708F, 0.0F, 0.0F)); + + PartDefinition pustule3 = body.addOrReplaceChild("pustule3", CubeListBuilder.create(), PartPose.offsetAndRotation(1.5724F, 9.1193F, -7.1515F, 2.8289F, -0.5338F, 2.1369F)); + + PartDefinition pustule_back_r1 = pustule3.addOrReplaceChild("pustule_back_r1", CubeListBuilder.create().texOffs(54, 9).addBox(3.4F, 0.0F, -4.7F, 2.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(1.309F, -2.9436F, -13.0622F, 2.0131F, -0.1273F, -1.056F)); + + PartDefinition pustule_belly_r1 = pustule3.addOrReplaceChild("pustule_belly_r1", CubeListBuilder.create().texOffs(54, 9).addBox(-2.0F, -0.6F, 5.0F, 2.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 0.0F, 0.0F, -2.0159F, 0.1667F, 2.0666F)); + + PartDefinition legs = partdefinition.addOrReplaceChild("legs", CubeListBuilder.create(), PartPose.offset(0.0F, 24.0F, 0.0F)); + + PartDefinition leg1 = legs.addOrReplaceChild("leg1", CubeListBuilder.create().texOffs(0, 16).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offset(-4.0F, -12.0F, 7.0F)); + + PartDefinition leg2 = legs.addOrReplaceChild("leg2", CubeListBuilder.create().texOffs(0, 16).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offset(4.0F, -12.0F, 7.0F)); + + PartDefinition leg3 = legs.addOrReplaceChild("leg3", CubeListBuilder.create().texOffs(0, 16).addBox(-2.0F, 0.0F, -1.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offset(-4.0F, -12.0F, -6.0F)); + + PartDefinition leg4 = legs.addOrReplaceChild("leg4", CubeListBuilder.create().texOffs(0, 16).addBox(-2.0F, 0.0F, -1.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)), PartPose.offset(4.0F, -12.0F, -6.0F)); + + PartDefinition pustule2 = leg4.addOrReplaceChild("pustule2", CubeListBuilder.create(), PartPose.offsetAndRotation(0.4249F, 7.2997F, 2.3458F, -2.5307F, 0.0F, 0.0F)); + + PartDefinition pustule_leg_r1 = pustule2.addOrReplaceChild("pustule_leg_r1", CubeListBuilder.create().texOffs(54, 9).addBox(-1.0F, 0.0F, -1.0F, 2.0F, 2.0F, 2.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(2.1064F, 2.3852F, -0.6084F, 0.1272F, 0.3997F, 1.5682F)); + + return LayerDefinition.create(meshdefinition, 64, 32); + } + + @Override + public void setupAnim(T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + this.head.xRot = headPitch * ((float)Math.PI / 180F); + this.head.yRot = netHeadYaw * ((float)Math.PI / 180F); + this.leg3.xRot = Mth.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount; + this.leg4.xRot = Mth.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount; + this.leg1.xRot = Mth.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount; + this.leg2.xRot = Mth.cos(limbSwing * 0.6662F) * 1.4F * limbSwingAmount; + } + + @Override + public void renderToBuffer(PoseStack poseStack, VertexConsumer vertexConsumer, int packedLight, int packedOverlay, int color) { + head.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + body.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + legs.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + } + + @Override + protected Iterable headParts() { + return ImmutableList.of(this.head); + } + + @Override + protected Iterable bodyParts() { + return ImmutableList.of(this.body, this.leg1, this.leg2, this.leg3, this.leg4); + } + +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cow/IrradiatedCowRenderer.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cow/IrradiatedCowRenderer.java new file mode 100644 index 0000000..1aed525 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/cow/IrradiatedCowRenderer.java @@ -0,0 +1,25 @@ +package net.nuclearteam.createnuclear.content.contraptions.irradiated.cow; + +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.resources.ResourceLocation; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.contraptions.irradiated.CNModelLayers; + +@OnlyIn(Dist.CLIENT) +public class IrradiatedCowRenderer extends MobRenderer> { + private static final ResourceLocation COW_LOCATION = CreateNuclear.asResource("textures/entity/irradiated_cow.png"); + + public IrradiatedCowRenderer(EntityRendererProvider.Context context) { + super(context, new IrradiatedCowModel<>(context.bakeLayer(CNModelLayers.IRRADIATED_COW)), 0.7f); + } + + /** + * Returns the location of an entity's texture. + */ + public ResourceLocation getTextureLocation(IrradiatedCow pEntity) { + return COW_LOCATION; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/wolf/IrradiatedWoldCollarLayer.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/wolf/IrradiatedWoldCollarLayer.java deleted file mode 100644 index 444e5ad..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/wolf/IrradiatedWoldCollarLayer.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.nuclearteam.createnuclear.content.contraptions.irradiated.wolf; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.entity.RenderLayerParent; -import net.minecraft.client.renderer.entity.layers.RenderLayer; -import net.minecraft.resources.ResourceLocation; - -import javax.annotation.ParametersAreNonnullByDefault; - -@ParametersAreNonnullByDefault -@SuppressWarnings("unused") -public class IrradiatedWoldCollarLayer extends RenderLayer> { - private static final ResourceLocation WOLF_COLLAR_LOCATION = ResourceLocation.withDefaultNamespace("textures/entity/wolf/wolf_collar.png"); - - public IrradiatedWoldCollarLayer(RenderLayerParent> renderer) { - super(renderer); - } - - @Override - public void render(PoseStack matrixStack, MultiBufferSource buffer, int packedLight, IrradiatedWolf livingEntity, float limbSwing, float limbSwingAmount, float partialTick, float ageInTicks, float netHeadYaw, float headPitch) { - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/wolf/IrradiatedWolf.java b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/wolf/IrradiatedWolf.java index 5df95a8..a9873d5 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/wolf/IrradiatedWolf.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/contraptions/irradiated/wolf/IrradiatedWolf.java @@ -4,7 +4,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.RegistryAccess; -import net.minecraft.core.particles.ItemParticleOption; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataAccessor; @@ -14,7 +13,6 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.BlockTags; -import net.minecraft.tags.DamageTypeTags; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.util.TimeUtil; @@ -37,9 +35,6 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.food.FoodProperties; import net.minecraft.world.item.*; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.enchantment.EnchantmentEffectComponents; -import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.ServerLevelAccessor; @@ -48,10 +43,9 @@ import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.pathfinder.PathType; import net.minecraft.world.phys.Vec3; -import net.neoforged.neoforge.common.ItemAbilities; -import net.neoforged.neoforge.event.EventHooks; import net.nuclearteam.createnuclear.CNEntityType; import net.nuclearteam.createnuclear.CNTags; +import net.nuclearteam.createnuclear.content.contraptions.irradiated.AnimalUtil; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @@ -66,8 +60,7 @@ public class IrradiatedWolf extends TamableAnimal implements NeutralMob { private static final EntityDataAccessor DATA_REMAINING_ANGER_TIME; public static final Predicate PREY_SELECTOR; private static final float START_HEALTH = 8.0F; - private static final float TAME_HEALTH = 40.0F; - private static final float ARMOR_REPAIR_UNIT = 0.125F; + private static final float TAME_HEALTH = 20.0F; private float interestedAngle; private float interestedAngleO; private boolean isWet; @@ -87,6 +80,7 @@ public IrradiatedWolf(EntityType entityType, Level lev protected void registerGoals() { this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(1, new WolfPanicGoal(1.5)); this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); this.goalSelector.addGoal(3, new IrradiatedWolfAvoidEntityGoal<>(this, Llama.class, 24.0F, (double) 1.5F, (double) 1.5F)); this.goalSelector.addGoal(4, new LeapAtTargetGoal(this, 0.4F)); @@ -157,7 +151,7 @@ protected SoundEvent getAmbientSound() { } protected SoundEvent getHurtSound(DamageSource damageSource) { - return this.canArmorAbsorb(damageSource) ? SoundEvents.WOLF_ARMOR_DAMAGE : SoundEvents.WOLF_HURT; + return SoundEvents.WOLF_HURT; } protected SoundEvent getDeathSound() { @@ -283,52 +277,23 @@ public boolean hurt(DamageSource source, float amount) { } } - public boolean canUseSlot(EquipmentSlot slot) { - return true; - } - - protected void actuallyHurt(DamageSource damageSource, float damageAmount) { - if (!this.canArmorAbsorb(damageSource)) { - super.actuallyHurt(damageSource, damageAmount); - } else { - ItemStack itemstack = this.getBodyArmorItem(); - int i = itemstack.getDamageValue(); - int j = itemstack.getMaxDamage(); - itemstack.hurtAndBreak(Mth.ceil(damageAmount), this, EquipmentSlot.BODY); - if (Crackiness.WOLF_ARMOR.byDamage(i, j) != Crackiness.WOLF_ARMOR.byDamage(this.getBodyArmorItem())) { - this.playSound(SoundEvents.WOLF_ARMOR_CRACK); - Level var7 = this.level(); - if (var7 instanceof ServerLevel) { - ServerLevel serverlevel = (ServerLevel)var7; - serverlevel.sendParticles(new ItemParticleOption(ParticleTypes.ITEM, Items.ARMADILLO_SCUTE.getDefaultInstance()), this.getX(), this.getY() + (double)1.0F, this.getZ(), 20, 0.2, 0.1, 0.2, 0.1); - } - } - } - - } - - private boolean canArmorAbsorb(DamageSource damageSource) { - return this.hasArmor() && !damageSource.is(DamageTypeTags.BYPASSES_WOLF_ARMOR); - } - protected void applyTamingSideEffects() { if (this.isTame()) { - this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)40.0F); - this.setHealth(40.0F); + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)TAME_HEALTH); + this.setHealth(TAME_HEALTH); } else { - this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)8.0F); + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)START_HEALTH); } } - protected void hurtArmor(DamageSource damageSource, float damageAmount) { - this.doHurtEquipment(damageSource, damageAmount, new EquipmentSlot[]{EquipmentSlot.BODY}); - } - public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); Item item = itemstack.getItem(); - if (!this.level().isClientSide || this.isBaby() && this.isFood(itemstack)) { + if (this.level().isClientSide) { + boolean flag = this.isOwnedBy(player) || this.isTame() || this.isFood(itemstack) && !this.isTame() && !this.isAngry(); + return flag ? InteractionResult.CONSUME : InteractionResult.PASS; + } else { if (this.isTame()) { if (this.isFood(itemstack) && this.getHealth() < this.getMaxHealth()) { FoodProperties foodproperties = itemstack.getFoodProperties(this); @@ -336,66 +301,25 @@ public InteractionResult mobInteract(Player player, InteractionHand hand) { this.heal(2.0F * f); itemstack.consume(1, player); this.gameEvent(GameEvent.EAT); - return InteractionResult.sidedSuccess(this.level().isClientSide()); + return InteractionResult.SUCCESS; } else { - - if (itemstack.is(Items.WOLF_ARMOR) && this.isOwnedBy(player) && this.getBodyArmorItem().isEmpty() && !this.isBaby()) { - this.setBodyArmorItem(itemstack.copyWithCount(1)); - itemstack.consume(1, player); - return InteractionResult.SUCCESS; - } else if (!itemstack.canPerformAction(ItemAbilities.SHEARS_REMOVE_ARMOR) || !this.isOwnedBy(player) || !this.hasArmor() || EnchantmentHelper.has(this.getBodyArmorItem(), EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE) && !player.isCreative()) { - if (((Ingredient)((ArmorMaterial)ArmorMaterials.ARMADILLO.value()).repairIngredient().get()).test(itemstack) && this.isInSittingPose() && this.hasArmor() && this.isOwnedBy(player) && this.getBodyArmorItem().isDamaged()) { - itemstack.shrink(1); - this.playSound(SoundEvents.WOLF_ARMOR_REPAIR); - ItemStack itemstack2 = this.getBodyArmorItem(); - int i = (int)((float)itemstack2.getMaxDamage() * 0.125F); - itemstack2.setDamageValue(Math.max(0, itemstack2.getDamageValue() - i)); - return InteractionResult.SUCCESS; - } else { - InteractionResult interactionresult = super.mobInteract(player, hand); - if (!interactionresult.consumesAction() && this.isOwnedBy(player)) { - this.setOrderedToSit(!this.isOrderedToSit()); - this.jumping = false; - this.navigation.stop(); - this.setTarget((LivingEntity)null); - return InteractionResult.SUCCESS_NO_ITEM_USED; - } else { - return interactionresult; - } - } + InteractionResult interactionresult = super.mobInteract(player, hand); + if (!interactionresult.consumesAction() && this.isOwnedBy(player)) { + this.setOrderedToSit(!this.isOrderedToSit()); + this.jumping = false; + this.navigation.stop(); + this.setTarget((LivingEntity)null); + return InteractionResult.SUCCESS_NO_ITEM_USED; } else { - itemstack.hurtAndBreak(1, player, getSlotForHand(hand)); - this.playSound(SoundEvents.ARMOR_UNEQUIP_WOLF); - ItemStack itemstack1 = this.getBodyArmorItem(); - this.setBodyArmorItem(ItemStack.EMPTY); - this.spawnAtLocation(itemstack1); - return InteractionResult.SUCCESS; + return interactionresult; } } - } else if (itemstack.is(Items.BONE) && !this.isAngry()) { - itemstack.consume(1, player); - this.tryToTame(player); - return InteractionResult.SUCCESS; + } else if (this.isFood(itemstack)) { + return AnimalUtil.blockTamingWip(player, this.level()); } else { return super.mobInteract(player, hand); } - } else { - boolean flag = this.isOwnedBy(player) || this.isTame() || itemstack.is(Items.BONE) && !this.isTame() && !this.isAngry(); - return flag ? InteractionResult.CONSUME : InteractionResult.PASS; - } - } - - private void tryToTame(Player player) { - if (this.random.nextInt(3) == 0 && !EventHooks.onAnimalTame(this, player)) { - this.tame(player); - this.navigation.stop(); - this.setTarget((LivingEntity)null); - this.setOrderedToSit(true); - this.level().broadcastEntityEvent(this, (byte)7); - } else { - this.level().broadcastEntityEvent(this, (byte)6); } - } public void handleEntityEvent(byte id) { @@ -453,11 +377,6 @@ public void setPersistentAngerTarget(@Nullable UUID target) { } - public boolean hasArmor() { - return this.getBodyArmorItem().is(Items.WOLF_ARMOR); - } - - @Nullable public IrradiatedWolf getBreedOffspring(ServerLevel level, AgeableMob otherParent) { return CNEntityType.IRRADIATED_WOLF.create(level); @@ -503,8 +422,9 @@ public boolean wantsToAttack(LivingEntity target, LivingEntity owner) { } } + @Override public boolean canBeLeashed() { - return !this.isAngry(); + return !this.isAngry() && super.canBeLeashed(); } public Vec3 getLeashOffset() { @@ -525,6 +445,16 @@ public static boolean checkWolfSpawnRules(EntityType wolf, LevelAccessor l PERSISTENT_ANGER_TIME = TimeUtil.rangeOfSeconds(20, 39); } + private class WolfPanicGoal extends PanicGoal { + public WolfPanicGoal(double speedModifier) { + super(IrradiatedWolf.this, speedModifier); + } + + protected boolean shouldPanic() { + return this.mob.isFreezing() || this.mob.isOnFire(); + } + } + static class IrradiatedWolfAvoidEntityGoal extends AvoidEntityGoal { private final IrradiatedWolf wolf; diff --git a/src/main/java/net/nuclearteam/createnuclear/content/effects/IodineEffect.java b/src/main/java/net/nuclearteam/createnuclear/content/effects/IodineEffect.java new file mode 100644 index 0000000..9862043 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/effects/IodineEffect.java @@ -0,0 +1,33 @@ +package net.nuclearteam.createnuclear.content.effects; + +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.resources.ResourceLocation; +import net.nuclearteam.createnuclear.CNAttributes; +import net.nuclearteam.createnuclear.CreateNuclear; + +public class IodineEffect extends MobEffect { + protected IodineEffect(MobEffectCategory pCategory, int pColor) { + super(pCategory, pColor); + + this.addAttributeModifier( + CNAttributes.IRRADIATED_RESISTANCE, + ResourceLocation.fromNamespaceAndPath( + CreateNuclear.MOD_ID, + "iodine_effect" + ), + 1D, + AttributeModifier.Operation.ADD_VALUE + ); + } + + public IodineEffect() { + this(MobEffectCategory.BENEFICIAL, 7328217); + } + + @Override + public boolean shouldApplyEffectTickThisTick(int pDuration, int pAmplifier) { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/effects/RadiationEffect.java b/src/main/java/net/nuclearteam/createnuclear/content/effects/RadiationEffect.java deleted file mode 100644 index e782a7c..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/effects/RadiationEffect.java +++ /dev/null @@ -1,80 +0,0 @@ -package net.nuclearteam.createnuclear.content.effects; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectCategory; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.nuclearteam.createnuclear.CNEffects; -import net.nuclearteam.createnuclear.CNPotions; -import net.nuclearteam.createnuclear.CNTags; -import net.nuclearteam.createnuclear.CreateNuclear; -import net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; - -public class RadiationEffect extends MobEffect { - - /** - * Constructs the RadiationEffect with harmful category and color. - * Also applies attribute modifiers to reduce speed, attack damage, and attack speed. - */ - public RadiationEffect() { - super(MobEffectCategory.HARMFUL, 15453236); // Custom color (hex value) - - // Reduces movement speed by 20% - this.addAttributeModifier(Attributes.MOVEMENT_SPEED, - ResourceLocation.fromNamespaceAndPath(CreateNuclear.MOD_ID, "radiation_movement_speed"), -0.2D, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL); - - // Reduces attack damage by 20% - this.addAttributeModifier(Attributes.ATTACK_DAMAGE, - ResourceLocation.fromNamespaceAndPath(CreateNuclear.MOD_ID, "radiation_attack_damage"), -0.2D, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL); - - // Reduces attack speed by 20% - this.addAttributeModifier(Attributes.ATTACK_SPEED, - ResourceLocation.fromNamespaceAndPath(CreateNuclear.MOD_ID, "radiation_attack_speed"), -0.2D, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL); - } - - /** - * Applies the radiation effect to the entity. - * - Does nothing if the entity is immune via tag. - * - Skips damage if the entity wears any anti-radiation armor. - * - Otherwise, applies magic damage based on the amplifier. - * - * @param livingEntity The affected living entity. - * @param amplifier The strength (level) of the effect. - */ - @Override - public boolean applyEffectTick(LivingEntity livingEntity, int amplifier) { - // If the entity is immune to radiation, remove the effect - if (livingEntity.getType().is(CNTags.CNEntityTags.IRRADIATED_IMMUNE.tag)) { - livingEntity.removeEffect(CNEffects.RADIATION); - return true; - } - - // Check if the entity is wearing any anti-radiation armor - boolean isWearingAntiRadiationArmor = false; - for (ItemStack armor : livingEntity.getArmorSlots()) { - if (AntiRadiationArmorItem.Armor.isArmored(armor)) { - isWearingAntiRadiationArmor = true; - break; - } - } - - // If protected by armor, do not apply damage - if (isWearingAntiRadiationArmor) { - return false; - - } - - // Apply radiation damage (magic type), scaled by amplifier - int damage = 1 << amplifier; - livingEntity.hurt(livingEntity.damageSources().magic(), damage); - return true; - } - - @Override - public boolean shouldApplyEffectTickThisTick(int duration, int amplifier) { - return duration >= 1; - } -} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/effects/VicinityEffect.java b/src/main/java/net/nuclearteam/createnuclear/content/effects/VicinityEffect.java new file mode 100644 index 0000000..2549b3f --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/effects/VicinityEffect.java @@ -0,0 +1,65 @@ +package net.nuclearteam.createnuclear.content.effects; + +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.*; + +public abstract class VicinityEffect extends MobEffect { + private final UnaryOperator areaSize; + private final Predicate filter; + + // Stores the GameTime tick when the cooldown expires for each entity + private final Map cooldowns = new HashMap<>(); + + protected VicinityEffect(MobEffectCategory category, int color, UnaryOperator areaSize, Predicate filter, Consumer timer) { + super(category, color); + + this.areaSize = areaSize; + this.filter = filter; + } + + @Override + public boolean applyEffectTick(LivingEntity entity, int amplifier) { + long currentTime = entity.level().getGameTime(); + + List nearbyEntities = entity.level().getEntities( + entity, + entity.getBoundingBox().inflate(areaSize.apply(amplifier)), + e -> e instanceof LivingEntity target && filter.test(target) + ); + + for (Entity nearbyEntity : nearbyEntities) { + LivingEntity nearby = (LivingEntity) nearbyEntity; + UUID entityUuid = nearby.getUUID(); + + // Check if the cooldown has expired + if (currentTime >= cooldowns.getOrDefault(entityUuid, 0L)) { + onContaminate(nearby); + + // Set a 100-tick (5 seconds) cooldown before refreshing the effect again + cooldowns.put(entityUuid, currentTime + 100); + } + } + return true; + } + + /** + * Called for each eligible nearby entity once its cooldown expires. Each subclass + * decides how it actually delivers the effect (e.g. RadiationEffect feeds the dose + * into RadiationCapability rather than adding a MobEffect directly). + */ + protected abstract void onContaminate(LivingEntity nearby); + + @Override + public boolean shouldApplyEffectTickThisTick(int duration, int amplifier) { + return duration % 5 == 0; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/enriching/campfire/EnrichingCampfireBlock.java b/src/main/java/net/nuclearteam/createnuclear/content/enriching/campfire/EnrichingCampfireBlock.java index b76720a..880fc58 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/enriching/campfire/EnrichingCampfireBlock.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/enriching/campfire/EnrichingCampfireBlock.java @@ -44,6 +44,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.nuclearteam.createnuclear.CNBlockEntityTypes; import net.nuclearteam.createnuclear.CNEffects; +import net.nuclearteam.createnuclear.content.radiation.capability.RadiationCapability; import org.jetbrains.annotations.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @@ -52,6 +53,8 @@ @ParametersAreNonnullByDefault @SuppressWarnings({"deprecation", "unused"}) public class EnrichingCampfireBlock extends BaseEntityBlock implements SimpleWaterloggedBlock, IBE { + private static final double CAMPFIRE_DOSE = 5.0D; + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( (enrichChampFireBlock) -> enrichChampFireBlock @@ -84,8 +87,8 @@ protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Lev @Override public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { - if (state.getValue(LIT) && entity instanceof LivingEntity) { - ((LivingEntity) entity).addEffect(new MobEffectInstance(CNEffects.RADIATION.getDelegate(), 100, 0)); + if (state.getValue(LIT) && entity instanceof LivingEntity livingEntity) { + RadiationCapability.applyContagion(livingEntity, CAMPFIRE_DOSE, 100); } super.entityInside(state, level, pos, entity); } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorClientExtensions.java b/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorClientExtensions.java new file mode 100644 index 0000000..167d1c9 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorClientExtensions.java @@ -0,0 +1,35 @@ +package net.nuclearteam.createnuclear.content.equipment.armor; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions; +import net.nuclearteam.createnuclear.content.contraptions.irradiated.CNModelLayers; +import net.nuclearteam.createnuclear.foundation.utility.ClothTagHelper; +import org.jetbrains.annotations.NotNull; + +public final class AntiRadiationArmorClientExtensions implements IClientItemExtensions { + private AntiRadiationArmorModel model; + + @Override + public @NotNull HumanoidModel getHumanoidArmorModel(LivingEntity livingEntity, ItemStack itemStack, EquipmentSlot equipmentSlot, HumanoidModel original) { + if (this.model == null) { + EntityModelSet entityModelSet = Minecraft.getInstance().getEntityModels(); + ModelPart root = entityModelSet.bakeLayer(CNModelLayers.ANTI_RADIATION_ARMOR); + this.model = new AntiRadiationArmorModel(root); + } + + // Forge copies the body pose + standard part visibility from `original` onto the + // model after this returns, but it can't tell LEGS from FEET (both make the vanilla + // legs visible) and knows nothing about our custom boot parts. We pass the slot so + // renderToBuffer can show legs for leggings vs. only boots for the FEET slot. + this.model.currentSlot = equipmentSlot; + return this.model; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorItem.java b/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorItem.java index 21f9491..a431e7f 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorItem.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorItem.java @@ -1,179 +1,92 @@ package net.nuclearteam.createnuclear.content.equipment.armor; -import com.simibubi.create.content.equipment.armor.BaseArmorItem; -import com.tterrag.registrate.util.entry.ItemEntry; +import com.tterrag.registrate.builders.ItemBuilder; +import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; +import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.Holder; -import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.EquipmentSlotGroup; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.*; +import net.minecraft.world.item.component.ItemAttributeModifiers; +import net.nuclearteam.createnuclear.CNAttributes; +import net.nuclearteam.createnuclear.CNDataComponents; import net.nuclearteam.createnuclear.CNItems; -import net.nuclearteam.createnuclear.CNTags.CNItemTags; import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.equipment.cloth.ClothItem.Cloths; -import java.util.EnumMap; -import java.util.Locale; -import java.util.Map; - -@SuppressWarnings("unused") -public class AntiRadiationArmorItem { - - public static final ArmorItem.Type HELMET = ArmorItem.Type.HELMET; - public static final ArmorItem.Type CHESTPLATE = ArmorItem.Type.CHESTPLATE; - public static final ArmorItem.Type LEGGINGS = ArmorItem.Type.LEGGINGS; - public static final ArmorItem.Type BOOTS = ArmorItem.Type.BOOTS; - public static final Holder ARMOR_MATERIAL = CNArmorMaterials.ANTI_RADIATION_SUIT; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancement; - public static class Helmet extends BaseArmorItem { - protected final DyeColor color; - - public Helmet(Properties properties, DyeColor color) { - super( - CNArmorMaterials.ANTI_RADIATION_SUIT, - HELMET, - properties, - CreateNuclear.asResource(String.format(Locale.ROOT, "%s_anti_radiation_suit", color.getName())) - ); - this.color = color; - } +@SuppressWarnings("unused") +@MethodsReturnNonnullByDefault +public class AntiRadiationArmorItem extends ArmorItem { + public static final double RADIATION_VALUE = 0.25; - public static TagKey getHelmetTag(String key) { - return key.equals("white") - ? CNItemTags.ANTI_RADIATION_ARMOR.tag - : CNItemTags.ANTI_RADIATION_HELMET_DYE.tag; - } + public AntiRadiationArmorItem(Holder material, ArmorItem.Type type, Item.Properties properties) { + super(material, type, properties); } - - public static class Chestplate extends BaseArmorItem { - protected final DyeColor color; - - public Chestplate(Properties properties, DyeColor color) { - super( - CNArmorMaterials.ANTI_RADIATION_SUIT, - CHESTPLATE, - properties, - CreateNuclear.asResource(String.format(Locale.ROOT, "%s_anti_radiation_suit", color.getName())) - ); - this.color = color; - - } - - public static TagKey getChestplateTag(String key) { - return key.equals("white") - ? CNItemTags.ANTI_RADIATION_ARMOR.tag - : CNItemTags.ANTI_RADIATION_CHESTPLATE_DYE.tag; - } + @Override + public ItemAttributeModifiers getDefaultAttributeModifiers() { + return super.getDefaultAttributeModifiers().withModifierAdded( + CNAttributes.IRRADIATED_RESISTANCE, + // The id must be unique per slot: modifiers are keyed by ResourceLocation, so sharing one id + // between the 4 pieces would make them overwrite each other instead of stacking to 1.0. + new AttributeModifier(CreateNuclear.asResource("armor_resistance_irradiation_" + this.getType().getName()), RADIATION_VALUE, AttributeModifier.Operation.ADD_VALUE), + EquipmentSlotGroup.bySlot(this.getType().getSlot()) + ); } - public static class Leggings extends BaseArmorItem { - protected final DyeColor color; - - public Leggings(Properties properties, DyeColor color) { - super( - CNArmorMaterials.ANTI_RADIATION_SUIT, - LEGGINGS, - properties, - CreateNuclear.asResource(String.format(Locale.ROOT, "%s_anti_radiation_suit", color.getName())) - ); - this.color = color; - - } - - public static TagKey getLeggingsTag(String key) { - return key.equals("white") - ? CNItemTags.ANTI_RADIATION_ARMOR.tag - : CNItemTags.ANTI_RADIATION_LEGGINGS_DYE.tag; - } + @Override + public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { + super.inventoryTick(stack, level, entity, slotId, isSelected); + if (level.isClientSide || !(entity instanceof Player player)) return; + if (!stack.has(CNDataComponents.CLOTH_COLOR)) return; + if (CNAdvancement.DYE_ANTI_RADIATION_ARMOR.isAlreadyAwardedTo(player)) return; + CNAdvancement.DYE_ANTI_RADIATION_ARMOR.awardTo(player); } - public static class Boot extends BaseArmorItem { - public Boot(Properties properties) { - super( - CNArmorMaterials.ANTI_RADIATION_SUIT, - BOOTS, - properties, - CreateNuclear.asResource(String.format(Locale.ROOT, "%s_anti_radiation_suit", DyeColor.WHITE.getName())) + public static NonNullUnaryOperator> setColorComponent(Cloths cloths) { + return b -> b + .properties(p -> p + .component(CNDataComponents.CLOTH_COLOR, Cloths.DEFAULT) ); - } } - - public enum Armor { - WHITE_ARMOR(DyeColor.WHITE), - YELLOW_ARMOR(DyeColor.YELLOW), - RED_ARMOR(DyeColor.RED), - BLUE_ARMOR(DyeColor.BLUE), - GREEN_ARMOR(DyeColor.GREEN), - BLACK_ARMOR(DyeColor.BLACK), - ORANGE_ARMOR(DyeColor.ORANGE), - PURPLE_ARMOR(DyeColor.PURPLE), - BROWN_ARMOR(DyeColor.BROWN), - PINK_ARMOR(DyeColor.PINK), - CYAN_ARMOR(DyeColor.CYAN), - LIGHT_GRAY_ARMOR(DyeColor.LIGHT_GRAY), - GRAY_ARMOR(DyeColor.GRAY), - LIGHT_BLUE_ARMOR(DyeColor.LIGHT_BLUE), - LIME_ARMOR(DyeColor.LIME), - MAGENTA_ARMOR(DyeColor.MAGENTA); - - private static final Map> helmetMap = new EnumMap<>(DyeColor.class); - private static final Map> chestplateMap = new EnumMap<>(DyeColor.class); - private static final Map> leggingsMap = new EnumMap<>(DyeColor.class); - - static { - for (DyeColor color : DyeColor.values()) { - helmetMap.put(color, CNItems.ANTI_RADIATION_HELMETS.get(color)); - chestplateMap.put(color, CNItems.ANTI_RADIATION_CHESTPLATES.get(color)); - leggingsMap.put(color, CNItems.ANTI_RADIATION_LEGGINGS.get(color)); - } - } - - private final DyeColor color; - - Armor(DyeColor dyeColor) { - this.color = dyeColor; - } - - public ItemEntry getHelmetItem() { - return helmetMap.get(this.color); - } - - public static ItemEntry getHelmetByColor(DyeColor color) { - return helmetMap.get(color); - } - - public ItemEntry getChestplateItem() { - return chestplateMap.get(this.color); - } - - public static ItemEntry getChestplateByColor(DyeColor color) { - return chestplateMap.get(color); + public static class Helmet extends AntiRadiationArmorItem implements IGoggleHelmet { + public Helmet(Properties p) { + super(CNArmorMaterials.ANTI_RADIATION_SUIT, Type.HELMET, p); } + } - public ItemEntry getLeggingsItem() { - return leggingsMap.get(this.color); + public static class Chestplate extends AntiRadiationArmorItem { + public Chestplate(Properties p) { + super(CNArmorMaterials.ANTI_RADIATION_SUIT, Type.CHESTPLATE, p); } + } - public static ItemEntry getLeggingsByColor(DyeColor color) { - return leggingsMap.get(color); + public static class Leggings extends AntiRadiationArmorItem { + public Leggings(Properties p) { + super(CNArmorMaterials.ANTI_RADIATION_SUIT, Type.LEGGINGS, p); } + } - public static boolean isArmored(ItemStack item) { - return helmetMap.values().stream().anyMatch(entry -> entry.is(item.getItem())) || - chestplateMap.values().stream().anyMatch(entry -> entry.is(item.getItem())) || - leggingsMap.values().stream().anyMatch(entry -> entry.is(item.getItem())) || - CNItems.ANTI_RADIATION_BOOTS.is(item.getItem()) - ; + public static class Boot extends AntiRadiationArmorItem { + public Boot(Properties p) { + super(CNArmorMaterials.ANTI_RADIATION_SUIT, Type.BOOTS, p); } + } - public static boolean isArmored2(ItemStack item) { - return CNItems.ANTI_RADIATION_HELMETS.contains(item.getItem()) - || CNItems.ANTI_RADIATION_CHESTPLATES.contains(item.getItem()) - || CNItems.ANTI_RADIATION_LEGGINGS.contains(item.getItem()) - || CNItems.ANTI_RADIATION_BOOTS.is(item.getItem()) - ; + public interface IGoggleHelmet { + static boolean isGoggleHelmet(LivingEntity entity) { + ItemStack headSlot = entity.getItemBySlot(EquipmentSlot.HEAD); + return CNItems.ANTI_RADIATION_HELMETS.isIn(headSlot); } } - } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorModel.java b/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorModel.java new file mode 100644 index 0000000..9795960 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorModel.java @@ -0,0 +1,99 @@ +package net.nuclearteam.createnuclear.content.equipment.armor; + + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.*; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; + +public class AntiRadiationArmorModel extends HumanoidModel { + private final ModelPart head; + private final ModelPart body; + private final ModelPart right_arm; + private final ModelPart left_arm; + private final ModelPart right_leg; + private final ModelPart left_leg; + private final ModelPart left_boot; + private final ModelPart right_boot; + + // Set per render pass by AntiRadiationArmorClientExtensions so renderToBuffer can show + // the legs for LEGS (leggings) but only the boots for FEET (boots) — Forge makes the + // vanilla leg parts visible for BOTH slots, so we disambiguate here. + public EquipmentSlot currentSlot = EquipmentSlot.HEAD; + + public AntiRadiationArmorModel(ModelPart root) { + super(root); + this.head = root.getChild("head"); + this.body = root.getChild("body"); + this.right_arm = root.getChild("right_arm"); + this.left_arm = root.getChild("left_arm"); + this.right_leg = root.getChild("right_leg"); + this.left_leg = root.getChild("left_leg"); + this.left_boot = root.getChild("left_boot"); + this.right_boot = root.getChild("right_boot"); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + // HumanoidModel's constructor requires a "hat" child; keep it empty. + partdefinition.addOrReplaceChild("hat", CubeListBuilder.create(), PartPose.ZERO); + + PartDefinition head = partdefinition.addOrReplaceChild("head", CubeListBuilder.create().texOffs(30, 0).addBox(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.2F)) + .texOffs(30, 16).addBox(-4.0F, -8.0F, -4.0F, 8.0F, 8.0F, 8.0F, new CubeDeformation(0.5F)), PartPose.offset(0.0F, 0.0F, 0.0F)); + + PartDefinition body = partdefinition.addOrReplaceChild("body", CubeListBuilder.create().texOffs(0, 19).addBox(-3.7F, 0.0F, -2.8F, 8.0F, 12.0F, 5.0F, new CubeDeformation(0.0F)) + .texOffs(0, 0).addBox(-4.4F, -1.0F, -3.1F, 9.0F, 13.0F, 6.0F, new CubeDeformation(0.0F)) + .texOffs(0, 36).addBox(-4.0F, 0.0F, -2.7F, 8.0F, 12.0F, 5.0F, new CubeDeformation(0.0F)) + .texOffs(64, 0).addBox(-4.5F, -1.0F, -3.0F, 9.0F, 13.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offset(0.0F, 0.0F, 0.0F)); + + PartDefinition right_arm = partdefinition.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(45, 32).mirror().addBox(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.45F)).mirror(false) + .texOffs(29, 32).mirror().addBox(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.55F)).mirror(false), PartPose.offset(-5.0F, 2.0F, 0.0F)); + + PartDefinition left_arm = partdefinition.addOrReplaceChild("left_arm", CubeListBuilder.create().texOffs(45, 32).addBox(-1.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.4F)) + .texOffs(29, 32).addBox(-1.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.5F)), PartPose.offset(5.0F, 2.0F, 0.0F)); + + PartDefinition right_leg = partdefinition.addOrReplaceChild("right_leg", CubeListBuilder.create().texOffs(29, 48).mirror().addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)).mirror(false) + .texOffs(45, 48).mirror().addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)).mirror(false), PartPose.offset(1.9F, 12.0F, 0.0F)); + + PartDefinition left_leg = partdefinition.addOrReplaceChild("left_leg", CubeListBuilder.create().texOffs(29, 48).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.0F)) + .texOffs(45, 48).addBox(-2.0F, 0.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offset(-1.9F, 12.0F, 0.0F)); + + partdefinition.addOrReplaceChild("left_boot", CubeListBuilder.create().texOffs(61, 39).addBox(-2.0F, 8.3F, -2.0F, 4.0F, 4.0F, 4.0F, new CubeDeformation(0.25F)), PartPose.offset(-1.9F, 12.0F, 0.0F)); + + partdefinition.addOrReplaceChild("right_boot", CubeListBuilder.create().texOffs(61, 39).mirror().addBox(-2.0F, 8.3F, -2.0F, 4.0F, 4.0F, 4.0F, new CubeDeformation(0.25F)).mirror(false), PartPose.offset(1.9F, 12.0F, 0.0F)); + + return LayerDefinition.create(meshdefinition, 96, 96); + } + + @Override + public void renderToBuffer(PoseStack poseStack, VertexConsumer vertexConsumer, int packedLight, int packedOverlay, int color) { + // Make the boots follow the (already animated) legs. + this.right_boot.copyFrom(this.right_leg); + this.left_boot.copyFrom(this.left_leg); + + // Control part visibility based on the slot being rendered + this.head.visible = this.currentSlot == EquipmentSlot.HEAD; + this.body.visible = this.currentSlot == EquipmentSlot.CHEST; + this.right_arm.visible = this.currentSlot == EquipmentSlot.CHEST; + this.left_arm.visible = this.currentSlot == EquipmentSlot.CHEST; + this.right_leg.visible = this.currentSlot == EquipmentSlot.LEGS; + this.left_leg.visible = this.currentSlot == EquipmentSlot.LEGS; + this.right_boot.visible = this.currentSlot == EquipmentSlot.FEET; + this.left_boot.visible = this.currentSlot == EquipmentSlot.FEET; + + if (this.head.visible) head.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + if (this.body.visible) body.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + if (this.right_arm.visible) right_arm.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + if (this.left_arm.visible) left_arm.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + if (this.right_leg.visible) right_leg.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + if (this.left_leg.visible) left_leg.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + if (this.right_boot.visible) right_boot.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + if (this.left_boot.visible) left_boot.render(poseStack, vertexConsumer, packedLight, packedOverlay, color); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/CNArmorMaterials.java b/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/CNArmorMaterials.java index de77dfe..77791ab 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/CNArmorMaterials.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/CNArmorMaterials.java @@ -1,12 +1,17 @@ package net.nuclearteam.createnuclear.content.equipment.armor; +import com.tterrag.registrate.builders.ItemBuilder; +import com.tterrag.registrate.util.nullness.NonNullBiConsumer; +import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ArmorItem.Type; import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.Item; import net.minecraft.world.item.crafting.Ingredient; import net.neoforged.bus.api.IEventBus; import net.nuclearteam.createnuclear.CNItems; @@ -48,8 +53,8 @@ private static Holder register(String name, int[] defense, int en float knockbackResistance, Supplier repairIngredient, List layers) { - EnumMap enumMap = new EnumMap<>(ArmorItem.Type.class); - for (ArmorItem.Type armorItem : ArmorItem.Type.values()) { + EnumMap enumMap = new EnumMap<>(Type.class); + for (Type armorItem : Type.values()) { enumMap.put(armorItem, defense[armorItem.ordinal()]); } @@ -63,9 +68,18 @@ public static void register(IEventBus eventBus) { ARMOR_MATERIALS.register(eventBus); } - public static int durabilityForType(ArmorItem.Type type) { + public static int durabilityForType(Type type) { int[] BASE_DURABILITY = {11, 16, 15, 13}; int durabilityMultiplier = 15; return BASE_DURABILITY[type.ordinal()] * durabilityMultiplier; } + + public static NonNullUnaryOperator> setArmorDurability(Type type, int factor) { + return b -> b.properties(p -> p.durability(type.getDurability(factor))); + } + + public static NonNullUnaryOperator> setArmorDurability(Type type) { + return setArmorDurability(type, 15); + } + } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/equipment/cloth/ClothItem.java b/src/main/java/net/nuclearteam/createnuclear/content/equipment/cloth/ClothItem.java index e9fbb67..b212c9c 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/equipment/cloth/ClothItem.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/equipment/cloth/ClothItem.java @@ -1,18 +1,22 @@ package net.nuclearteam.createnuclear.content.equipment.cloth; -import com.simibubi.create.api.data.recipe.BaseRecipeProvider.GeneratedRecipe; +import com.mojang.serialization.Codec; import com.tterrag.registrate.util.entry.ItemEntry; +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.util.StringRepresentable; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; import net.nuclearteam.createnuclear.CNItems; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.*; -import java.util.function.Function; + +import javax.annotation.Nullable; +import java.util.EnumMap; +import java.util.Map; @SuppressWarnings("unused") public class ClothItem extends Item { - private final DyeColor color; public ClothItem(Item.Properties properties, DyeColor color) { @@ -20,112 +24,32 @@ public ClothItem(Item.Properties properties, DyeColor color) { this.color = color; } - public static class DyeRecipeList implements Iterable { - - private static final int COLOR_AMOUNT = DyeColor.values().length; - protected final GeneratedRecipe[] recipes = new GeneratedRecipe[getColorCount()]; - - public DyeRecipeList(Function<@NotNull DyeColor, GeneratedRecipe> filler) { - for (DyeColor color : DyeColor.values()) { - recipes[color.ordinal()] = filler.apply(color); - } - } - - protected int getColorCount() { - return COLOR_AMOUNT; - } - - public GeneratedRecipe get(@Nullable DyeColor color) { - return recipes[color.ordinal()]; - } - - public GeneratedRecipe[] toArrays() { - return Arrays.copyOf(recipes, recipes.length); - } - - @NotNull - @Override - public Iterator iterator() { - return new Iterator<>() { - private int index = 0; - @Override - public boolean hasNext() { - return index < recipes.length; - } - @Override - public GeneratedRecipe next() { - if (!hasNext()) throw new NoSuchElementException(); - return recipes[index++]; - } - }; - } - - public static class NullableDyedRecipeList extends DyeRecipeList { - public NullableDyedRecipeList(Function<@Nullable DyeColor, GeneratedRecipe> filter) { - super(filter); - recipes[recipes.length - 1] = filter.apply(null); - } - @Override - protected int getColorCount() { - return COLOR_AMOUNT + 1; - } - @Override - public GeneratedRecipe get(@Nullable DyeColor color) { - return color == null ? recipes[recipes.length - 1] : super.get(color); - } - } - + public DyeColor getColor() { + return color; } - public static class DyeItemList implements Iterable> { - - private static final int COLOR_AMOUNT = DyeColor.values().length; + /** + * Wraps an ItemStack with content-based equals/hashCode, since ItemStack itself only offers + * identity equality and NeoForge requires data component values to implement both properly. + */ + public record ClothItemStack(ItemStack stack) { + public static final Codec CODEC = ItemStack.CODEC.xmap(ClothItemStack::new, ClothItemStack::stack); + public static final StreamCodec STREAM_CODEC = ItemStack.STREAM_CODEC.map(ClothItemStack::new, ClothItemStack::stack); - private final ItemEntry[] entry = new ItemEntry[COLOR_AMOUNT]; - - public DyeItemList(Function> filler) { - for (DyeColor color : DyeColor.values()) { - entry[color.ordinal()] = filler.apply(color); - } - } - - @SuppressWarnings("unchecked") - public ItemEntry get(DyeColor color) { - return (ItemEntry) entry[color.ordinal()]; - } - - public boolean contains(Item block) { - for (ItemEntry entry : entry) { - if (entry.is(block)) return true; - } - return false; - } - - @SuppressWarnings("unchecked") - public ItemEntry[] toArray() { - return (ItemEntry[]) Arrays.copyOf(entry, entry.length); + @Override + public boolean equals(Object other) { + return other instanceof ClothItemStack(ItemStack stack1) + && ItemStack.isSameItemSameComponents(this.stack, stack1); } @Override - public Iterator> iterator() { - return new Iterator<>() { - private int index = 0; - @Override - public boolean hasNext() { - return index < entry.length; - } - @SuppressWarnings("unchecked") - @Override - public ItemEntry next() { - if (!hasNext()) throw new NoSuchElementException(); - return (ItemEntry) entry[index++]; - } - }; + public int hashCode() { + return ItemStack.hashItemAndComponents(this.stack); } - } - public enum Cloths { + @MethodsReturnNonnullByDefault + public enum Cloths implements StringRepresentable { WHITE_CLOTH(DyeColor.WHITE), YELLOW_CLOTH(DyeColor.YELLOW), RED_CLOTH(DyeColor.RED), @@ -141,29 +65,59 @@ public enum Cloths { GRAY_CLOTH(DyeColor.GRAY), LIGHT_BLUE_CLOTH(DyeColor.LIGHT_BLUE), LIME_CLOTH(DyeColor.LIME), - MAGENTA_CLOTH(DyeColor.MAGENTA); + MAGENTA_CLOTH(DyeColor.MAGENTA), + DEFAULT(null, "default"); - private static final Map> clothMap = new EnumMap<>(DyeColor.class); + private static Map> clothMap; - static { - for (DyeColor color : DyeColor.values()) { - clothMap.put(color, CNItems.CLOTHS.get(color)); + private static Map> clothMap() { + if (clothMap == null) { + clothMap = new EnumMap<>(DyeColor.class); + for (DyeColor color : DyeColor.values()) { + clothMap.put(color, CNItems.CLOTHS.get(color)); + } } + return clothMap; } + @Nullable private final DyeColor color; + private final String serializedName; Cloths(DyeColor color) { + this(color, color.getSerializedName()); + } + + Cloths(@Nullable DyeColor color, String serializedName) { this.color = color; + this.serializedName = serializedName; } + @Nullable public ItemEntry getItem() { - return clothMap.get(this.color); + return color != null ? clothMap().get(color) : null; } public static ItemEntry getByColor(DyeColor color) { - return clothMap.get(color); + return clothMap().get(color); } + public static Cloths of(@Nullable DyeColor color) { + if (color == null) return DEFAULT; + for (Cloths c : values()) { + if (c.color == color) return c; + } + return DEFAULT; + } + + @Override + public String getSerializedName() { + return serializedName; + } + + @Nullable + public DyeColor getDyeColor() { + return color; + } } } \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNAdvancedEntityModel.java b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNAdvancedEntityModel.java new file mode 100644 index 0000000..6fc682b --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNAdvancedEntityModel.java @@ -0,0 +1,32 @@ +package net.nuclearteam.createnuclear.content.explosion; + +import net.minecraft.world.entity.Entity; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +public abstract class CNAdvancedEntityModel extends CNBasicEntityModel { + private float movementScale = 1.0F; + public int texWidth = 32; + public int texHeight = 32; + + public void updateDefaultPose() { + this.getAllParts().forEach(CNAdvancedModelBox::updateDefaultPose); + } + + public void resetToDefaultPose() { + this.getAllParts().forEach(CNAdvancedModelBox::resetToDefaultPose); + } + + public float getMovementScale() { + return this.movementScale; + } + + public void setRotateAngle(CNAdvancedModelBox model, float x, float y, float z) { + model.rotateAngleX = x; + model.rotateAngleY = y; + model.rotateAngleZ = z; + } + + public abstract Iterable getAllParts(); +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNAdvancedModelBox.java b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNAdvancedModelBox.java new file mode 100644 index 0000000..5cbfad7 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNAdvancedModelBox.java @@ -0,0 +1,208 @@ +package net.nuclearteam.createnuclear.content.explosion; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; +import it.unimi.dsi.fastutil.objects.ObjectListIterator; +import net.minecraft.util.Mth; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.joml.Matrix3f; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.joml.Vector4f; + +@OnlyIn(Dist.CLIENT) +public class CNAdvancedModelBox extends CNBasicModelPart { + public float defaultRotationX; + public float defaultRotationY; + public float defaultRotationZ; + public float defaultPositionX; + public float defaultPositionY; + public float defaultPositionZ; + public float scaleX; + public float scaleY; + public float scaleZ; + public int textureOffsetX; + public int textureOffsetY; + public boolean scaleChildren; + private CNAdvancedEntityModel model; + private CNAdvancedModelBox parent; + public ObjectList cubeList; + public ObjectList childModels; + private float textureWidth; + private float textureHeight; + public String boxName; + + public CNAdvancedModelBox(CNAdvancedEntityModel model, String name) { + super(model); + this.scaleX = 1.0F; + this.scaleY = 1.0F; + this.scaleZ = 1.0F; + this.boxName = ""; + this.textureWidth = (float)model.texWidth; + this.textureHeight = (float)model.texHeight; + this.model = model; + this.cubeList = new ObjectArrayList(); + this.childModels = new ObjectArrayList(); + this.boxName = name; + } + + public CNAdvancedModelBox(CNAdvancedEntityModel model) { + this(model, null); + this.textureWidth = (float)model.texWidth; + this.textureHeight = (float)model.texHeight; + this.cubeList = new ObjectArrayList(); + this.childModels = new ObjectArrayList(); + } + + public CNBasicModelPart addBox(String p_217178_1_, float p_217178_2_, float p_217178_3_, float p_217178_4_, int p_217178_5_, int p_217178_6_, int p_217178_7_, float p_217178_8_, int p_217178_9_, int p_217178_10_) { + this.setTextureOffset(p_217178_9_, p_217178_10_); + this.addBox(this.textureOffsetX, this.textureOffsetY, p_217178_2_, p_217178_3_, p_217178_4_, (float)p_217178_5_, (float)p_217178_6_, (float)p_217178_7_, p_217178_8_, p_217178_8_, p_217178_8_, this.mirror, false); + return this; + } + + public CNBasicModelPart addBox(float p_228300_1_, float p_228300_2_, float p_228300_3_, float p_228300_4_, float p_228300_5_, float p_228300_6_) { + this.addBox(this.textureOffsetX, this.textureOffsetY, p_228300_1_, p_228300_2_, p_228300_3_, p_228300_4_, p_228300_5_, p_228300_6_, 0.0F, 0.0F, 0.0F, this.mirror, false); + return this; + } + + public CNBasicModelPart addBox(float p_228304_1_, float p_228304_2_, float p_228304_3_, float p_228304_4_, float p_228304_5_, float p_228304_6_, boolean p_228304_7_) { + this.addBox(this.textureOffsetX, this.textureOffsetY, p_228304_1_, p_228304_2_, p_228304_3_, p_228304_4_, p_228304_5_, p_228304_6_, 0.0F, 0.0F, 0.0F, p_228304_7_, false); + return this; + } + + public void addBox(float p_228301_1_, float p_228301_2_, float p_228301_3_, float p_228301_4_, float p_228301_5_, float p_228301_6_, float p_228301_7_) { + this.addBox(this.textureOffsetX, this.textureOffsetY, p_228301_1_, p_228301_2_, p_228301_3_, p_228301_4_, p_228301_5_, p_228301_6_, p_228301_7_, p_228301_7_, p_228301_7_, this.mirror, false); + } + + public void addBox(float p_228302_1_, float p_228302_2_, float p_228302_3_, float p_228302_4_, float p_228302_5_, float p_228302_6_, float p_228302_7_, float p_228302_8_, float p_228302_9_) { + this.addBox(this.textureOffsetX, this.textureOffsetY, p_228302_1_, p_228302_2_, p_228302_3_, p_228302_4_, p_228302_5_, p_228302_6_, p_228302_7_, p_228302_8_, p_228302_9_, this.mirror, false); + } + + public void addBox(float p_228303_1_, float p_228303_2_, float p_228303_3_, float p_228303_4_, float p_228303_5_, float p_228303_6_, float p_228303_7_, boolean p_228303_8_) { + this.addBox(this.textureOffsetX, this.textureOffsetY, p_228303_1_, p_228303_2_, p_228303_3_, p_228303_4_, p_228303_5_, p_228303_6_, p_228303_7_, p_228303_7_, p_228303_7_, p_228303_8_, false); + } + + private void addBox(int p_228305_1_, int p_228305_2_, float p_228305_3_, float p_228305_4_, float p_228305_5_, float p_228305_6_, float p_228305_7_, float p_228305_8_, float p_228305_9_, float p_228305_10_, float p_228305_11_, boolean p_228305_12_, boolean p_228305_13_) { + this.cubeList.add(new CNTabulaModelRenderUtils.ModelBox(p_228305_1_, p_228305_2_, p_228305_3_, p_228305_4_, p_228305_5_, p_228305_6_, p_228305_7_, p_228305_8_, p_228305_9_, p_228305_10_, p_228305_11_, p_228305_12_, this.textureWidth, this.textureHeight)); + } + + public void setScale(float scaleX, float scaleY, float scaleZ) { + this.scaleX = scaleX; + this.scaleY = scaleY; + this.scaleZ = scaleZ; + } + + public void updateDefaultPose() { + this.defaultRotationX = this.rotateAngleX; + this.defaultRotationY = this.rotateAngleY; + this.defaultRotationZ = this.rotateAngleZ; + this.defaultPositionX = this.rotationPointX; + this.defaultPositionY = this.rotationPointY; + this.defaultPositionZ = this.rotationPointZ; + } + + public void resetToDefaultPose() { + this.rotateAngleX = this.defaultRotationX; + this.rotateAngleY = this.defaultRotationY; + this.rotateAngleZ = this.defaultRotationZ; + this.rotationPointX = this.defaultPositionX; + this.rotationPointY = this.defaultPositionY; + this.rotationPointZ = this.defaultPositionZ; + } + + public void addChild(CNBasicModelPart child) { + super.addChild(child); + this.childModels.add(child); + if (child instanceof CNAdvancedModelBox advancedChild) { + advancedChild.setParent(this); + } + } + + public CNAdvancedModelBox getParent() { + return this.parent; + } + + public void setParent(CNAdvancedModelBox parent) { + this.parent = parent; + } + + public void translateAndRotate(PoseStack matrixStackIn) { + matrixStackIn.translate(this.rotationPointX / 16.0F, this.rotationPointY / 16.0F, (double)(this.rotationPointZ / 16.0F)); + if (this.rotateAngleZ != 0.0F) { + matrixStackIn.mulPose(Axis.ZP.rotation(this.rotateAngleZ)); + } + + if (this.rotateAngleY != 0.0F) { + matrixStackIn.mulPose(Axis.YP.rotation(this.rotateAngleY)); + } + + if (this.rotateAngleX != 0.0F) { + matrixStackIn.mulPose(Axis.XP.rotation(this.rotateAngleX)); + } + + matrixStackIn.scale(this.scaleX, this.scaleY, this.scaleZ); + } + + public void render(PoseStack p_228309_1_, VertexConsumer p_228309_2_, int p_228309_3_, int p_228309_4_, float p_228309_5_, float p_228309_6_, float p_228309_7_, float p_228309_8_) { + if (this.showModel && (!this.cubeList.isEmpty() || !this.childModels.isEmpty())) { + p_228309_1_.pushPose(); + this.translateAndRotate(p_228309_1_); + this.doRender(p_228309_1_.last(), p_228309_2_, p_228309_3_, p_228309_4_, p_228309_5_, p_228309_6_, p_228309_7_, p_228309_8_); + ObjectListIterator var9 = this.childModels.iterator(); + if (!this.scaleChildren) { + p_228309_1_.scale(1.0F / Math.max(this.scaleX, 1.0E-4F), 1.0F / Math.max(this.scaleY, 1.0E-4F), 1.0F / Math.max(this.scaleZ, 1.0E-4F)); + } + + while(var9.hasNext()) { + CNBasicModelPart lvt_10_1_ = (CNBasicModelPart)var9.next(); + lvt_10_1_.render(p_228309_1_, p_228309_2_, p_228309_3_, p_228309_4_, p_228309_5_, p_228309_6_, p_228309_7_, p_228309_8_); + } + + p_228309_1_.popPose(); + } + + } + + private void doRender(PoseStack.Pose p_228306_1_, VertexConsumer p_228306_2_, int p_228306_3_, int p_228306_4_, float p_228306_5_, float p_228306_6_, float p_228306_7_, float p_228306_8_) { + Matrix4f lvt_9_1_ = p_228306_1_.pose(); + Matrix3f lvt_10_1_ = p_228306_1_.normal(); + ObjectListIterator var11 = this.cubeList.iterator(); + + while(var11.hasNext()) { + CNTabulaModelRenderUtils.ModelBox lvt_12_1_ = (CNTabulaModelRenderUtils.ModelBox)var11.next(); + + for(CNTabulaModelRenderUtils.TexturedQuad lvt_16_1_ : lvt_12_1_.quads) { + Vector3f lvt_17_1_ = new Vector3f(lvt_16_1_.normal); + lvt_17_1_.mul(lvt_10_1_); + float lvt_18_1_ = lvt_17_1_.x(); + float lvt_19_1_ = lvt_17_1_.y(); + float lvt_20_1_ = lvt_17_1_.z(); + + for(int lvt_21_1_ = 0; lvt_21_1_ < 4; ++lvt_21_1_) { + CNTabulaModelRenderUtils.PositionTextureVertex lvt_22_1_ = lvt_16_1_.vertexPositions[lvt_21_1_]; + float lvt_23_1_ = lvt_22_1_.position.x() / 16.0F; + float lvt_24_1_ = lvt_22_1_.position.y() / 16.0F; + float lvt_25_1_ = lvt_22_1_.position.z() / 16.0F; + Vector4f lvt_26_1_ = new Vector4f(lvt_23_1_, lvt_24_1_, lvt_25_1_, 1.0F); + lvt_26_1_.mul(lvt_9_1_); + p_228306_2_.addVertex(lvt_26_1_.x(), lvt_26_1_.y(), lvt_26_1_.z()).setColor(p_228306_5_, p_228306_6_, p_228306_7_, p_228306_8_).setUv(lvt_22_1_.textureU, lvt_22_1_.textureV).setOverlay(p_228306_4_).setLight(p_228306_3_).setNormal(lvt_18_1_, lvt_19_1_, lvt_20_1_); + } + } + } + + } + + public CNAdvancedEntityModel getModel() { + return this.model; + } + + public CNAdvancedModelBox setTextureOffset(int textureOffsetX, int textureOffsetY) { + this.textureOffsetX = textureOffsetX; + this.textureOffsetY = textureOffsetY; + return this; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNBasicEntityModel.java b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNBasicEntityModel.java new file mode 100644 index 0000000..53ab4e2 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNBasicEntityModel.java @@ -0,0 +1,40 @@ +package net.nuclearteam.createnuclear.content.explosion; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import java.util.function.Function; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; + +public abstract class CNBasicEntityModel extends EntityModel { + public int textureWidth; + public int textureHeight; + + protected CNBasicEntityModel() { + this(RenderType::entityCutoutNoCull); + } + + protected CNBasicEntityModel(Function p_102613_) { + super(p_102613_); + this.textureWidth = 64; + this.textureHeight = 32; + } + + @Override + public void renderToBuffer(PoseStack p_103013_, VertexConsumer p_103014_, int p_103015_, int p_103016_, int color) { + float p_103017_ = (float) (color >> 16 & 255) / 255.0F; + float p_103018_ = (float) (color >> 8 & 255) / 255.0F; + float p_103019_ = (float) (color & 255) / 255.0F; + float p_103020_ = (float) (color >> 24 & 255) / 255.0F; + this.parts().forEach((p_103030_) -> p_103030_.render(p_103013_, p_103014_, p_103015_, p_103016_, p_103017_, p_103018_, p_103019_, p_103020_)); + } + + public abstract Iterable parts(); + + public abstract void setupAnim(T var1, float var2, float var3, float var4, float var5, float var6); + + public void prepareMobModel(T p_102614_, float p_102615_, float p_102616_, float p_102617_) { + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNBasicModelPart.java b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNBasicModelPart.java new file mode 100644 index 0000000..a26e854 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNBasicModelPart.java @@ -0,0 +1,315 @@ +package net.nuclearteam.createnuclear.content.explosion; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; +import it.unimi.dsi.fastutil.objects.ObjectListIterator; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.joml.Matrix3f; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.joml.Vector4f; + +@OnlyIn(Dist.CLIENT) +public class CNBasicModelPart { + public float textureWidth; + public float textureHeight; + public int textureOffsetX; + public int textureOffsetY; + public float rotationPointX; + public float rotationPointY; + public float rotationPointZ; + public float rotateAngleX; + public float rotateAngleY; + public float rotateAngleZ; + public boolean mirror; + public boolean showModel; + private final ObjectList cubeList; + private final ObjectList childModels; + + public CNBasicModelPart(CNBasicEntityModel model) { + this.textureWidth = 64.0F; + this.textureHeight = 32.0F; + this.showModel = true; + this.cubeList = new ObjectArrayList(); + this.childModels = new ObjectArrayList(); + this.setTextureSize(model.textureWidth, model.textureHeight); + } + + public CNBasicModelPart(CNBasicEntityModel model, int texOffX, int texOffY) { + this(model.textureWidth, model.textureHeight, texOffX, texOffY); + } + + public CNBasicModelPart(int textureWidthIn, int textureHeightIn, int textureOffsetXIn, int textureOffsetYIn) { + this.textureWidth = 64.0F; + this.textureHeight = 32.0F; + this.showModel = true; + this.cubeList = new ObjectArrayList(); + this.childModels = new ObjectArrayList(); + this.setTextureSize(textureWidthIn, textureHeightIn); + this.setTextureOffset(textureOffsetXIn, textureOffsetYIn); + } + + private CNBasicModelPart() { + this.textureWidth = 64.0F; + this.textureHeight = 32.0F; + this.showModel = true; + this.cubeList = new ObjectArrayList(); + this.childModels = new ObjectArrayList(); + } + + public CNBasicModelPart getModelAngleCopy() { + CNBasicModelPart CNBasicModelPart = new CNBasicModelPart(); + CNBasicModelPart.copyModelAngles(this); + return CNBasicModelPart; + } + + public void copyModelAngles(CNBasicModelPart CNBasicModelPartIn) { + this.rotateAngleX = CNBasicModelPartIn.rotateAngleX; + this.rotateAngleY = CNBasicModelPartIn.rotateAngleY; + this.rotateAngleZ = CNBasicModelPartIn.rotateAngleZ; + this.rotationPointX = CNBasicModelPartIn.rotationPointX; + this.rotationPointY = CNBasicModelPartIn.rotationPointY; + this.rotationPointZ = CNBasicModelPartIn.rotationPointZ; + } + + public void addChild(CNBasicModelPart renderer) { + this.childModels.add(renderer); + } + + public CNBasicModelPart setTextureOffset(int x, int y) { + this.textureOffsetX = x; + this.textureOffsetY = y; + return this; + } + + public CNBasicModelPart addBox(String partName, float x, float y, float z, int width, int height, int depth, float delta, int texX, int texY) { + this.setTextureOffset(texX, texY); + this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, (float)width, (float)height, (float)depth, delta, delta, delta, this.mirror, false); + return this; + } + + public CNBasicModelPart addBox(float x, float y, float z, float width, float height, float depth) { + this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, width, height, depth, 0.0F, 0.0F, 0.0F, this.mirror, false); + return this; + } + + public CNBasicModelPart addBox(float x, float y, float z, float width, float height, float depth, boolean mirrorIn) { + this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, width, height, depth, 0.0F, 0.0F, 0.0F, mirrorIn, false); + return this; + } + + public void addBox(float x, float y, float z, float width, float height, float depth, float delta) { + this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, width, height, depth, delta, delta, delta, this.mirror, false); + } + + public void addBox(float x, float y, float z, float width, float height, float depth, float deltaX, float deltaY, float deltaZ) { + this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, width, height, depth, deltaX, deltaY, deltaZ, this.mirror, false); + } + + public void addBox(float x, float y, float z, float width, float height, float depth, float delta, boolean mirrorIn) { + this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, width, height, depth, delta, delta, delta, mirrorIn, false); + } + + private void addBox(int texOffX, int texOffY, float x, float y, float z, float width, float height, float depth, float deltaX, float deltaY, float deltaZ, boolean mirorIn, boolean p_228305_13_) { + this.cubeList.add(new CNBasicModelPart.ModelBox(texOffX, texOffY, x, y, z, width, height, depth, deltaX, deltaY, deltaZ, mirorIn, this.textureWidth, this.textureHeight)); + } + + public void setRotationPoint(float rotationPointXIn, float rotationPointYIn, float rotationPointZIn) { + this.rotationPointX = rotationPointXIn; + this.rotationPointY = rotationPointYIn; + this.rotationPointZ = rotationPointZIn; + } + + public void render(PoseStack matrixStackIn, VertexConsumer bufferIn, int packedLightIn, int packedOverlayIn) { + this.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, 1.0F, 1.0F, 1.0F, 1.0F); + } + + public void render(PoseStack matrixStackIn, VertexConsumer bufferIn, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha) { + if (this.showModel && (!this.cubeList.isEmpty() || !this.childModels.isEmpty())) { + matrixStackIn.pushPose(); + this.translateRotate(matrixStackIn); + this.doRender(matrixStackIn.last(), bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha); + ObjectListIterator var9 = this.childModels.iterator(); + + while(var9.hasNext()) { + CNBasicModelPart CNBasicModelPart = (CNBasicModelPart)var9.next(); + CNBasicModelPart.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha); + } + + matrixStackIn.popPose(); + } + + } + + public void translateRotate(PoseStack matrixStackIn) { + matrixStackIn.translate((double)(this.rotationPointX / 16.0F), (double)(this.rotationPointY / 16.0F), (double)(this.rotationPointZ / 16.0F)); + if (this.rotateAngleZ != 0.0F) { + matrixStackIn.mulPose(Axis.ZP.rotation(this.rotateAngleZ)); + } + + if (this.rotateAngleY != 0.0F) { + matrixStackIn.mulPose(Axis.YP.rotation(this.rotateAngleY)); + } + + if (this.rotateAngleX != 0.0F) { + matrixStackIn.mulPose(Axis.XP.rotation(this.rotateAngleX)); + } + + } + + private void doRender(PoseStack.Pose matrixEntryIn, VertexConsumer bufferIn, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha) { + Matrix4f matrix4f = matrixEntryIn.pose(); + Matrix3f matrix3f = matrixEntryIn.normal(); + ObjectListIterator var11 = this.cubeList.iterator(); + + while(var11.hasNext()) { + CNBasicModelPart.ModelBox CNBasicModelPart$modelbox = (CNBasicModelPart.ModelBox)var11.next(); + + for(CNBasicModelPart.TexturedQuad CNBasicModelPart$texturedquad : CNBasicModelPart$modelbox.quads) { + Vector3f vector3f = new Vector3f(CNBasicModelPart$texturedquad.normal); + vector3f.mul(matrix3f); + float f = vector3f.x(); + float f1 = vector3f.y(); + float f2 = vector3f.z(); + + for(int i = 0; i < 4; ++i) { + CNBasicModelPart.PositionTextureVertex CNBasicModelPart$positiontexturevertex = CNBasicModelPart$texturedquad.vertexPositions[i]; + float f3 = CNBasicModelPart$positiontexturevertex.position.x() / 16.0F; + float f4 = CNBasicModelPart$positiontexturevertex.position.y() / 16.0F; + float f5 = CNBasicModelPart$positiontexturevertex.position.z() / 16.0F; + Vector4f vector4f = new Vector4f(f3, f4, f5, 1.0F); + vector4f.mul(matrix4f); + bufferIn.addVertex(vector4f.x(), vector4f.y(), vector4f.z()).setColor(red, green, blue, alpha).setUv(CNBasicModelPart$positiontexturevertex.textureU, CNBasicModelPart$positiontexturevertex.textureV).setOverlay(packedOverlayIn).setLight(packedLightIn).setNormal(f, f1, f2); + } + } + } + + } + + public CNBasicModelPart setTextureSize(int textureWidthIn, int textureHeightIn) { + this.textureWidth = (float)textureWidthIn; + this.textureHeight = (float)textureHeightIn; + return this; + } + + public CNBasicModelPart.ModelBox getRandomCube(RandomSource randomIn) { + return this.cubeList.size() > 0 ? (CNBasicModelPart.ModelBox)this.cubeList.get(randomIn.nextInt(this.cubeList.size())) : null; + } + + @OnlyIn(Dist.CLIENT) + public static class ModelBox { + private final CNBasicModelPart.TexturedQuad[] quads; + public final float posX1; + public final float posY1; + public final float posZ1; + public final float posX2; + public final float posY2; + public final float posZ2; + + public ModelBox(int texOffX, int texOffY, float x, float y, float z, float width, float height, float depth, float deltaX, float deltaY, float deltaZ, boolean mirorIn, float texWidth, float texHeight) { + this.posX1 = x; + this.posY1 = y; + this.posZ1 = z; + this.posX2 = x + width; + this.posY2 = y + height; + this.posZ2 = z + depth; + this.quads = new CNBasicModelPart.TexturedQuad[6]; + float f = x + width; + float f1 = y + height; + float f2 = z + depth; + x -= deltaX; + y -= deltaY; + z -= deltaZ; + f += deltaX; + f1 += deltaY; + f2 += deltaZ; + if (mirorIn) { + float f3 = f; + f = x; + x = f3; + } + + CNBasicModelPart.PositionTextureVertex CNBasicModelPart$positiontexturevertex7 = new CNBasicModelPart.PositionTextureVertex(x, y, z, 0.0F, 0.0F); + CNBasicModelPart.PositionTextureVertex CNBasicModelPart$positiontexturevertex = new CNBasicModelPart.PositionTextureVertex(f, y, z, 0.0F, 8.0F); + CNBasicModelPart.PositionTextureVertex CNBasicModelPart$positiontexturevertex1 = new CNBasicModelPart.PositionTextureVertex(f, f1, z, 8.0F, 8.0F); + CNBasicModelPart.PositionTextureVertex CNBasicModelPart$positiontexturevertex2 = new CNBasicModelPart.PositionTextureVertex(x, f1, z, 8.0F, 0.0F); + CNBasicModelPart.PositionTextureVertex CNBasicModelPart$positiontexturevertex3 = new CNBasicModelPart.PositionTextureVertex(x, y, f2, 0.0F, 0.0F); + CNBasicModelPart.PositionTextureVertex CNBasicModelPart$positiontexturevertex4 = new CNBasicModelPart.PositionTextureVertex(f, y, f2, 0.0F, 8.0F); + CNBasicModelPart.PositionTextureVertex CNBasicModelPart$positiontexturevertex5 = new CNBasicModelPart.PositionTextureVertex(f, f1, f2, 8.0F, 8.0F); + CNBasicModelPart.PositionTextureVertex CNBasicModelPart$positiontexturevertex6 = new CNBasicModelPart.PositionTextureVertex(x, f1, f2, 8.0F, 0.0F); + float f4 = (float)texOffX; + float f5 = (float)texOffX + depth; + float f6 = (float)texOffX + depth + width; + float f7 = (float)texOffX + depth + width + width; + float f8 = (float)texOffX + depth + width + depth; + float f9 = (float)texOffX + depth + width + depth + width; + float f10 = (float)texOffY; + float f11 = (float)texOffY + depth; + float f12 = (float)texOffY + depth + height; + this.quads[2] = new CNBasicModelPart.TexturedQuad(new CNBasicModelPart.PositionTextureVertex[]{CNBasicModelPart$positiontexturevertex4, CNBasicModelPart$positiontexturevertex3, CNBasicModelPart$positiontexturevertex7, CNBasicModelPart$positiontexturevertex}, f5, f10, f6, f11, texWidth, texHeight, mirorIn, Direction.DOWN); + this.quads[3] = new CNBasicModelPart.TexturedQuad(new CNBasicModelPart.PositionTextureVertex[]{CNBasicModelPart$positiontexturevertex1, CNBasicModelPart$positiontexturevertex2, CNBasicModelPart$positiontexturevertex6, CNBasicModelPart$positiontexturevertex5}, f6, f11, f7, f10, texWidth, texHeight, mirorIn, Direction.UP); + this.quads[1] = new CNBasicModelPart.TexturedQuad(new CNBasicModelPart.PositionTextureVertex[]{CNBasicModelPart$positiontexturevertex7, CNBasicModelPart$positiontexturevertex3, CNBasicModelPart$positiontexturevertex6, CNBasicModelPart$positiontexturevertex2}, f4, f11, f5, f12, texWidth, texHeight, mirorIn, Direction.WEST); + this.quads[4] = new CNBasicModelPart.TexturedQuad(new CNBasicModelPart.PositionTextureVertex[]{CNBasicModelPart$positiontexturevertex, CNBasicModelPart$positiontexturevertex7, CNBasicModelPart$positiontexturevertex2, CNBasicModelPart$positiontexturevertex1}, f5, f11, f6, f12, texWidth, texHeight, mirorIn, Direction.NORTH); + this.quads[0] = new CNBasicModelPart.TexturedQuad(new CNBasicModelPart.PositionTextureVertex[]{CNBasicModelPart$positiontexturevertex4, CNBasicModelPart$positiontexturevertex, CNBasicModelPart$positiontexturevertex1, CNBasicModelPart$positiontexturevertex5}, f6, f11, f8, f12, texWidth, texHeight, mirorIn, Direction.EAST); + this.quads[5] = new CNBasicModelPart.TexturedQuad(new CNBasicModelPart.PositionTextureVertex[]{CNBasicModelPart$positiontexturevertex3, CNBasicModelPart$positiontexturevertex4, CNBasicModelPart$positiontexturevertex5, CNBasicModelPart$positiontexturevertex6}, f8, f11, f9, f12, texWidth, texHeight, mirorIn, Direction.SOUTH); + } + } + + @OnlyIn(Dist.CLIENT) + static class PositionTextureVertex { + public final Vector3f position; + public final float textureU; + public final float textureV; + + public PositionTextureVertex(float x, float y, float z, float texU, float texV) { + this(new Vector3f(x, y, z), texU, texV); + } + + public CNBasicModelPart.PositionTextureVertex setTextureUV(float texU, float texV) { + return new CNBasicModelPart.PositionTextureVertex(this.position, texU, texV); + } + + public PositionTextureVertex(Vector3f posIn, float texU, float texV) { + this.position = posIn; + this.textureU = texU; + this.textureV = texV; + } + } + + @OnlyIn(Dist.CLIENT) + static class TexturedQuad { + public final CNBasicModelPart.PositionTextureVertex[] vertexPositions; + public final Vector3f normal; + + public TexturedQuad(CNBasicModelPart.PositionTextureVertex[] positionsIn, float u1, float v1, float u2, float v2, float texWidth, float texHeight, boolean mirrorIn, Direction directionIn) { + this.vertexPositions = positionsIn; + float f = 0.0F / texWidth; + float f1 = 0.0F / texHeight; + positionsIn[0] = positionsIn[0].setTextureUV(u2 / texWidth - f, v1 / texHeight + f1); + positionsIn[1] = positionsIn[1].setTextureUV(u1 / texWidth + f, v1 / texHeight + f1); + positionsIn[2] = positionsIn[2].setTextureUV(u1 / texWidth + f, v2 / texHeight - f1); + positionsIn[3] = positionsIn[3].setTextureUV(u2 / texWidth - f, v2 / texHeight - f1); + if (mirrorIn) { + int i = positionsIn.length; + + for(int j = 0; j < i / 2; ++j) { + CNBasicModelPart.PositionTextureVertex CNBasicModelPart$positiontexturevertex = positionsIn[j]; + positionsIn[j] = positionsIn[i - 1 - j]; + positionsIn[i - 1 - j] = CNBasicModelPart$positiontexturevertex; + } + } + + this.normal = directionIn.step(); + if (mirrorIn) { + this.normal.mul(-1.0F, 1.0F, 1.0F); + } + + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNNuclearExplosionSound.java b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNNuclearExplosionSound.java new file mode 100644 index 0000000..39094a1 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNNuclearExplosionSound.java @@ -0,0 +1,46 @@ +package net.nuclearteam.createnuclear.content.explosion; + +import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance; +import net.minecraft.client.resources.sounds.SoundInstance; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; + +public class CNNuclearExplosionSound extends AbstractTickableSoundInstance { + + private int tickCount = 0; + private final int duration; + private final int fadesAt; + private final float fadeInBy; + + public CNNuclearExplosionSound(SoundEvent soundEvent, double x, double y, double z, int duration, int fadesAt, float fadeInBy, boolean looping) { + super(soundEvent, SoundSource.NEUTRAL, SoundInstance.createUnseededRandom()); + this.attenuation = Attenuation.LINEAR; + this.looping = looping; + this.x = x; + this.y = y; + this.z = z; + this.duration = duration; + this.fadesAt = fadesAt; + this.fadeInBy = fadeInBy; + this.delay = 0; + this.volume = 20; + } + + public void tick() { + if(tickCount < this.duration){ + if(tickCount >= fadesAt){ + float shrinkVolumeFor = 1F / Math.max(this.duration - fadesAt, 1F); + volume = Math.max(0, volume - shrinkVolumeFor); + }else if(volume < 1F){ + volume = Math.min(1F, volume + fadeInBy); + } + tickCount++; + }else{ + stop(); + } + } + + public boolean canStartSilent() { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNTabulaModelRenderUtils.java b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNTabulaModelRenderUtils.java new file mode 100644 index 0000000..53dea7f --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/explosion/CNTabulaModelRenderUtils.java @@ -0,0 +1,119 @@ +package net.nuclearteam.createnuclear.content.explosion; + +import net.minecraft.core.Direction; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import org.joml.Vector3f; + +public class CNTabulaModelRenderUtils { + @OnlyIn(Dist.CLIENT) + static class PositionTextureVertex { + public final Vector3f position; + public final float textureU; + public final float textureV; + + public PositionTextureVertex(float p_i1158_1_, float p_i1158_2_, float p_i1158_3_, float p_i1158_4_, float p_i1158_5_) { + this(new Vector3f(p_i1158_1_, p_i1158_2_, p_i1158_3_), p_i1158_4_, p_i1158_5_); + } + + public PositionTextureVertex setTextureUV(float p_78240_1_, float p_78240_2_) { + return new PositionTextureVertex(this.position, p_78240_1_, p_78240_2_); + } + + public PositionTextureVertex(Vector3f p_i225952_1_, float p_i225952_2_, float p_i225952_3_) { + this.position = p_i225952_1_; + this.textureU = p_i225952_2_; + this.textureV = p_i225952_3_; + } + } + + @OnlyIn(Dist.CLIENT) + static class TexturedQuad { + public final PositionTextureVertex[] vertexPositions; + public final Vector3f normal; + + public TexturedQuad(PositionTextureVertex[] p_i225951_1_, float p_i225951_2_, float p_i225951_3_, float p_i225951_4_, float p_i225951_5_, float p_i225951_6_, float p_i225951_7_, boolean p_i225951_8_, Direction p_i225951_9_) { + this.vertexPositions = p_i225951_1_; + float lvt_10_1_ = 0.0F / p_i225951_6_; + float lvt_11_1_ = 0.0F / p_i225951_7_; + p_i225951_1_[0] = p_i225951_1_[0].setTextureUV(p_i225951_4_ / p_i225951_6_ - lvt_10_1_, p_i225951_3_ / p_i225951_7_ + lvt_11_1_); + p_i225951_1_[1] = p_i225951_1_[1].setTextureUV(p_i225951_2_ / p_i225951_6_ + lvt_10_1_, p_i225951_3_ / p_i225951_7_ + lvt_11_1_); + p_i225951_1_[2] = p_i225951_1_[2].setTextureUV(p_i225951_2_ / p_i225951_6_ + lvt_10_1_, p_i225951_5_ / p_i225951_7_ - lvt_11_1_); + p_i225951_1_[3] = p_i225951_1_[3].setTextureUV(p_i225951_4_ / p_i225951_6_ - lvt_10_1_, p_i225951_5_ / p_i225951_7_ - lvt_11_1_); + if (p_i225951_8_) { + int lvt_12_1_ = p_i225951_1_.length; + + for(int lvt_13_1_ = 0; lvt_13_1_ < lvt_12_1_ / 2; ++lvt_13_1_) { + PositionTextureVertex lvt_14_1_ = p_i225951_1_[lvt_13_1_]; + p_i225951_1_[lvt_13_1_] = p_i225951_1_[lvt_12_1_ - 1 - lvt_13_1_]; + p_i225951_1_[lvt_12_1_ - 1 - lvt_13_1_] = lvt_14_1_; + } + } + + this.normal = p_i225951_9_.step(); + if (p_i225951_8_) { + this.normal.mul(-1.0F, 1.0F, 1.0F); + } + + } + } + + @OnlyIn(Dist.CLIENT) + public static class ModelBox { + public final TexturedQuad[] quads; + public final float posX1; + public final float posY1; + public final float posZ1; + public final float posX2; + public final float posY2; + public final float posZ2; + + public ModelBox(int p_i225950_1_, int p_i225950_2_, float p_i225950_3_, float p_i225950_4_, float p_i225950_5_, float p_i225950_6_, float p_i225950_7_, float p_i225950_8_, float p_i225950_9_, float p_i225950_10_, float p_i225950_11_, boolean p_i225950_12_, float p_i225950_13_, float p_i225950_14_) { + this.posX1 = p_i225950_3_; + this.posY1 = p_i225950_4_; + this.posZ1 = p_i225950_5_; + this.posX2 = p_i225950_3_ + p_i225950_6_; + this.posY2 = p_i225950_4_ + p_i225950_7_; + this.posZ2 = p_i225950_5_ + p_i225950_8_; + this.quads = new TexturedQuad[6]; + float lvt_15_1_ = p_i225950_3_ + p_i225950_6_; + float lvt_16_1_ = p_i225950_4_ + p_i225950_7_; + float lvt_17_1_ = p_i225950_5_ + p_i225950_8_; + p_i225950_3_ -= p_i225950_9_; + p_i225950_4_ -= p_i225950_10_; + p_i225950_5_ -= p_i225950_11_; + lvt_15_1_ += p_i225950_9_; + lvt_16_1_ += p_i225950_10_; + lvt_17_1_ += p_i225950_11_; + if (p_i225950_12_) { + float lvt_18_1_ = lvt_15_1_; + lvt_15_1_ = p_i225950_3_; + p_i225950_3_ = lvt_18_1_; + } + + PositionTextureVertex lvt_18_2_ = new PositionTextureVertex(p_i225950_3_, p_i225950_4_, p_i225950_5_, 0.0F, 0.0F); + PositionTextureVertex lvt_19_1_ = new PositionTextureVertex(lvt_15_1_, p_i225950_4_, p_i225950_5_, 0.0F, 8.0F); + PositionTextureVertex lvt_20_1_ = new PositionTextureVertex(lvt_15_1_, lvt_16_1_, p_i225950_5_, 8.0F, 8.0F); + PositionTextureVertex lvt_21_1_ = new PositionTextureVertex(p_i225950_3_, lvt_16_1_, p_i225950_5_, 8.0F, 0.0F); + PositionTextureVertex lvt_22_1_ = new PositionTextureVertex(p_i225950_3_, p_i225950_4_, lvt_17_1_, 0.0F, 0.0F); + PositionTextureVertex lvt_23_1_ = new PositionTextureVertex(lvt_15_1_, p_i225950_4_, lvt_17_1_, 0.0F, 8.0F); + PositionTextureVertex lvt_24_1_ = new PositionTextureVertex(lvt_15_1_, lvt_16_1_, lvt_17_1_, 8.0F, 8.0F); + PositionTextureVertex lvt_25_1_ = new PositionTextureVertex(p_i225950_3_, lvt_16_1_, lvt_17_1_, 8.0F, 0.0F); + float lvt_26_1_ = (float)p_i225950_1_; + float lvt_27_1_ = (float)p_i225950_1_ + p_i225950_8_; + float lvt_28_1_ = (float)p_i225950_1_ + p_i225950_8_ + p_i225950_6_; + float lvt_29_1_ = (float)p_i225950_1_ + p_i225950_8_ + p_i225950_6_ + p_i225950_6_; + float lvt_30_1_ = (float)p_i225950_1_ + p_i225950_8_ + p_i225950_6_ + p_i225950_8_; + float lvt_31_1_ = (float)p_i225950_1_ + p_i225950_8_ + p_i225950_6_ + p_i225950_8_ + p_i225950_6_; + float lvt_32_1_ = (float)p_i225950_2_; + float lvt_33_1_ = (float)p_i225950_2_ + p_i225950_8_; + float lvt_34_1_ = (float)p_i225950_2_ + p_i225950_8_ + p_i225950_7_; + this.quads[2] = new TexturedQuad(new PositionTextureVertex[]{lvt_23_1_, lvt_22_1_, lvt_18_2_, lvt_19_1_}, lvt_27_1_, lvt_32_1_, lvt_28_1_, lvt_33_1_, p_i225950_13_, p_i225950_14_, p_i225950_12_, Direction.DOWN); + this.quads[3] = new TexturedQuad(new PositionTextureVertex[]{lvt_20_1_, lvt_21_1_, lvt_25_1_, lvt_24_1_}, lvt_28_1_, lvt_33_1_, lvt_29_1_, lvt_32_1_, p_i225950_13_, p_i225950_14_, p_i225950_12_, Direction.UP); + this.quads[1] = new TexturedQuad(new PositionTextureVertex[]{lvt_18_2_, lvt_22_1_, lvt_25_1_, lvt_21_1_}, lvt_26_1_, lvt_33_1_, lvt_27_1_, lvt_34_1_, p_i225950_13_, p_i225950_14_, p_i225950_12_, Direction.WEST); + this.quads[4] = new TexturedQuad(new PositionTextureVertex[]{lvt_19_1_, lvt_18_2_, lvt_21_1_, lvt_20_1_}, lvt_27_1_, lvt_33_1_, lvt_28_1_, lvt_34_1_, p_i225950_13_, p_i225950_14_, p_i225950_12_, Direction.NORTH); + this.quads[0] = new TexturedQuad(new PositionTextureVertex[]{lvt_23_1_, lvt_19_1_, lvt_20_1_, lvt_24_1_}, lvt_28_1_, lvt_33_1_, lvt_30_1_, lvt_34_1_, p_i225950_13_, p_i225950_14_, p_i225950_12_, Direction.EAST); + this.quads[5] = new TexturedQuad(new PositionTextureVertex[]{lvt_22_1_, lvt_23_1_, lvt_24_1_, lvt_25_1_}, lvt_30_1_, lvt_33_1_, lvt_31_1_, lvt_34_1_, p_i225950_13_, p_i225950_14_, p_i225950_12_, Direction.SOUTH); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/explosion/NuclearExplosionEntity.java b/src/main/java/net/nuclearteam/createnuclear/content/explosion/NuclearExplosionEntity.java new file mode 100644 index 0000000..bd141a4 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/explosion/NuclearExplosionEntity.java @@ -0,0 +1,236 @@ +package net.nuclearteam.createnuclear.content.explosion; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.nuclearteam.createnuclear.*; +import net.nuclearteam.createnuclear.foundation.utility.Maths; +import net.nuclearteam.createnuclear.CNDamageTypes; + +import java.util.List; +import java.util.Stack; + +public class NuclearExplosionEntity extends Entity { + + private boolean spawnedParticle = false; + private Stack destroyingChunks = new Stack<>(); + private static final EntityDataAccessor SIZE = SynchedEntityData.defineId(NuclearExplosionEntity.class, EntityDataSerializers.FLOAT); + private static final EntityDataAccessor NO_GRIEFING = SynchedEntityData.defineId(NuclearExplosionEntity.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor INTENTIONAL_GAME_DESIGN = SynchedEntityData.defineId(NuclearExplosionEntity.class, EntityDataSerializers.BOOLEAN); + private boolean loadingChunks = false; + + + public NuclearExplosionEntity(EntityType entityType, Level level) { + super(entityType, level); + } + + + + public void tick() { + super.tick(); + int chunksAffected = getChunksAffected(); + int radius = chunksAffected * 15; + if (!spawnedParticle) { + spawnedParticle = true; + int particleY = (int) Math.ceil(this.getY()); + while (particleY > level().getMinBuildHeight() && particleY > this.getY() - radius / 2F && isDestroyable(level().getBlockState(BlockPos.containing(this.getX(), particleY, this.getZ())))) { + particleY--; + } + level().addAlwaysVisibleParticle(CNParticleRegistry.NUCLEAR_MUSHROOM_CLOUD.get(), true, this.getX(), particleY + 2, this.getZ(), this.getSize(), isIntentionalGameDesign() ? 1.0F : 0.0F, 0); + } + if (tickCount > 40 && destroyingChunks.isEmpty()) { + this.remove(RemovalReason.DISCARDED); + } else { + if (!level().isClientSide && !isNoGriefing()) { + if (!loadingChunks && !this.isRemoved()) { + loadingChunks = true; + loadChunksAround(true); + } + if (destroyingChunks.isEmpty()) { + BlockPos center = this.blockPosition(); + int chunks = chunksAffected; + for (int i = -chunks; i <= chunks; i++) { + for (int j = -chunks; j <= chunks; j++) { + for (int k = -chunks; k <= chunks; k++) { + destroyingChunks.push(center.offset(i * 16, j * 16, k * 16)); + } + } + } + destroyingChunks.sort((blockPos1, blockPos2) -> Double.compare(blockPos2.distManhattan(this.blockPosition()), blockPos1.distManhattan(this.blockPosition()))); + } else { + int tickChunkCount = Math.min(destroyingChunks.size(), 3); + for (int i = 0; i < tickChunkCount; i++) { + removeChunk(radius); + } + } + } + AABB killBox = this.getBoundingBox().inflate(radius + radius * 0.5F, radius * 0.6, radius + radius * 0.5F); + float flingStrength = getSize() * 0.33F; + float maximumDistance = radius + radius * 0.5F + 1; + + for (LivingEntity entity : this.level().getEntitiesOfClass(LivingEntity.class, killBox)) { + float dist = entity.distanceTo(this); + float damage = calculateDamage(dist, maximumDistance); + Vec3 vec3 = entity.position().subtract(this.position()).add(0, 0.3, 0).normalize(); + float playerFling = entity instanceof Player ? 0.5F * flingStrength : flingStrength; + + if (damage > 0) { + if (entity.getType().is(CNTags.CNEntityTags.IRRADIATED_IMMUNE.tag)) { + damage *= 0.25F; + playerFling *= 0.1F; + + } + + if (damage > 0) { + entity.hurt(CNDamageTypes.radiation(entity.level()), damage); + } + } + entity.setDeltaMovement(vec3.scale(damage * 0.1F * playerFling)); + } + } + } + + @Override + public void remove(Entity.RemovalReason removalReason) { + if (!level().isClientSide && loadingChunks) { + loadingChunks = false; + loadChunksAround(false); + } + super.remove(removalReason); + } + + + private int getChunksAffected() { + return (int) Math.ceil(this.getSize()); + } + + private void loadChunksAround(boolean load) { + if (this.level() instanceof ServerLevel serverLevel) { + ChunkPos chunkPos = new ChunkPos(this.blockPosition()); + int dist = Math.max(getChunksAffected(), serverLevel.getServer().getPlayerList().getViewDistance() / 2); + for (int i = -dist; i <= dist; i++) { + for (int j = -dist; j <= dist; j++) { + serverLevel.setChunkForced(chunkPos.x + i, chunkPos.z + j, load); + } + } + } + } + + private float calculateDamage(float dist, float max) { + float revert = (max - dist) / max; + float baseDmg = this.getSize() <= 1.5F ? 100 : 100 + (this.getSize() - 1.5F) * 400; + return revert * baseDmg; + } + + private void removeChunk(int radius) { + BlockPos chunkCorner = destroyingChunks.pop(); + BlockPos.MutableBlockPos carve = new BlockPos.MutableBlockPos(); + BlockPos.MutableBlockPos carveBelow = new BlockPos.MutableBlockPos(); + carve.set(chunkCorner); + carveBelow.set(chunkCorner); + float itemDropModifier = 0.025F / Math.min(1, this.getSize()); + + + Explosion dummyExplosion = new Explosion(level(), this, this.getX(), this.getY(), this.getZ(), 10.0F, false, Explosion.BlockInteraction.DESTROY); + + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + for (int y = 15; y >= 0; y--) { + boolean canSetToFire = false; + carve.set(chunkCorner.getX() + x, Mth.clamp(chunkCorner.getY() + y, level().getMinBuildHeight(), level().getMaxBuildHeight()), chunkCorner.getZ() + z); + float widthSimplexNoise1 = (Maths.sampleNoise3D((float)carve.getX(), (float)carve.getY(), (float)carve.getZ(), (float)radius) - 0.5F) * 0.45F + 0.55F; + double yDist = Maths.smin(0.6F - Math.abs(this.blockPosition().getY() - carve.getY()) / (float) radius, 0.6F, 0.2F); + double distToCenter = carve.distToLowCornerSqr(this.blockPosition().getX(), carve.getY() - 1, this.blockPosition().getZ()); + double targetRadius = yDist * (radius + widthSimplexNoise1 * radius) * radius; + + if (distToCenter <= targetRadius) { + BlockState state = level().getBlockState(carve); + if ((!state.isAir() || !state.getFluidState().isEmpty()) && isDestroyable(state)) { + carveBelow.set(carve.getX(), carve.getY() - 1, carve.getZ()); + canSetToFire = true; + + + + // 1. Create an immutable copy of the position + BlockPos immutablePos = carve.immutable(); + + // 2. Call the explosion behavior + state.onBlockExploded(level(), immutablePos, dummyExplosion); + + // 3. onBlockExploded() doesn't remove plain vanilla blocks (e.g. stone/dirt) by + // itself, so force removal here and let items drop normally + if (level().getBlockState(immutablePos).is(state.getBlock())) { + level().destroyBlock(immutablePos, true); + } + } + } + if (canSetToFire && random.nextFloat() < 0.15 && !level().getBlockState(carveBelow).isAir()) { + level().setBlockAndUpdate(carveBelow.above(), CNBlocks.ENRICHING_FIRE.get().defaultBlockState()); + } + } + } + } + } + + private boolean isDestroyable(BlockState state) { + return !(state.getBlock().getExplosionResistance() >= 3600000); + } + + @Override + protected void defineSynchedData(SynchedEntityData.Builder builder) { + builder.define(SIZE, 1.0F); + builder.define(NO_GRIEFING, false); + builder.define(INTENTIONAL_GAME_DESIGN, false); + } + + public float getSize() { + return this.entityData.get(SIZE); + } + + public void setSize(float f) { + this.entityData.set(SIZE, f); + } + + public boolean isNoGriefing() { + return this.entityData.get(NO_GRIEFING); + } + + public void setNoGriefing(boolean noGriefing) { + this.entityData.set(NO_GRIEFING, noGriefing); + } + + public boolean isIntentionalGameDesign() { + return this.entityData.get(INTENTIONAL_GAME_DESIGN); + } + + public void setIntentionalGameDesign(boolean intentionalGameDesign) { + this.entityData.set(INTENTIONAL_GAME_DESIGN, intentionalGameDesign); + } + + + @Override + protected void readAdditionalSaveData(CompoundTag compoundTag) { + loadingChunks = compoundTag.getBoolean("WasLoadingChunks"); + } + + @Override + protected void addAdditionalSaveData(CompoundTag compoundTag) { + compoundTag.putBoolean("WasLoadingChunks", loadingChunks); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/kinetics/fan/processing/CNFanProcessingTypes.java b/src/main/java/net/nuclearteam/createnuclear/content/kinetics/fan/processing/CNFanProcessingTypes.java index 0f99368..f42de01 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/kinetics/fan/processing/CNFanProcessingTypes.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/kinetics/fan/processing/CNFanProcessingTypes.java @@ -12,6 +12,7 @@ import net.minecraft.core.particles.ParticleTypes; import net.minecraft.util.RandomSource; import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; @@ -23,6 +24,8 @@ import net.minecraft.world.phys.Vec3; import net.nuclearteam.createnuclear.*; import net.nuclearteam.createnuclear.content.enriching.campfire.EnrichingCampfireBlock; +import net.nuclearteam.createnuclear.content.radiation.capability.RadiationCapability; +import net.nuclearteam.createnuclear.foundation.damagesTypes.CNDamageSources; import javax.annotation.Nullable; import java.util.List; @@ -32,12 +35,14 @@ @SuppressWarnings("unused") public class CNFanProcessingTypes { public static final EnrichedType ENRICHED = register("enriched", new EnrichedType()); + public static final SnowPowderType SNOW_POWDER = register("snow_powder", new SnowPowderType()); private static final Map LEGACY_NAME_MAP; static { Object2ReferenceOpenHashMap map = new Object2ReferenceOpenHashMap<>(); map.put("ENRICHED", ENRICHED); + map.put("SNOW_POWDER", SNOW_POWDER); map.trim(); LEGACY_NAME_MAP = map; } @@ -62,6 +67,7 @@ public static FanProcessingType parseLegacy(String str) { } public static class EnrichedType implements FanProcessingType { + private static final double FAN_ENRICHING_DOSE = 5.0D; @Override public boolean isValidAt(Level level, BlockPos pos) { @@ -115,7 +121,64 @@ public void morphAirFlow(AirFlowParticleAccess particleAccess, RandomSource rand @Override public void affectEntity(Entity entity, Level level) { if (entity instanceof LivingEntity livingEntity) { - livingEntity.addEffect(new MobEffectInstance(CNEffects.RADIATION.getDelegate(), 10, 0, true, true)); + RadiationCapability.applyContagion(livingEntity, FAN_ENRICHING_DOSE, 10); + livingEntity.hurt(CNDamageSources.fanRadiation(level), 1); + } + } + } + + public static class SnowPowderType implements FanProcessingType { + + @Override + public boolean isValidAt(Level level, BlockPos pos) { + BlockState state = level.getBlockState(pos); + return CNTags.CNBlockTags.FAN_PROCESSING_CATALYSTS_SNOW_POWDER.matches(state); + } + + @Override + public int getPriority() { + return 301; + } + + @Override + public boolean canProcess(ItemStack stack, Level level) { + Optional>> recipe = CNRecipeTypes.SNOW_POWDER.find(new SingleRecipeInput(stack), level); + return recipe.isPresent(); + } + + @Nullable + @Override + public List process(ItemStack stack, Level level) { + return CNRecipeTypes.SNOW_POWDER.find(new SingleRecipeInput(stack), level) + .map(RecipeHolder::value) + .map(r -> RecipeApplier.applyRecipeOn(level, stack, r, true)) + .orElse(null); + } + + @Override + public void spawnProcessingParticles(Level level, Vec3 pos) { + if (level.random.nextInt(8) != 0) return; + pos = pos.add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1) + .multiply(1, 0.5f, 1) + .normalize() + .scale(0.15f) + ); + level.addParticle(ParticleTypes.SNOWFLAKE, pos.x, pos.y + .45f, pos.z, 0.0, 0.0, 0.0); + if (level.random.nextInt(2) != 0) level.addParticle(ParticleTypes.SNEEZE, pos.x, pos.y + .25f, pos.z, 0.0, 0.0, 0.0); + } + + @Override + public void morphAirFlow(AirFlowParticleAccess particleAccess, RandomSource random) { + particleAccess.setColor(Color.mixColors(0x0, 0x49FFFB, random.nextFloat())); + particleAccess.setAlpha(1f); + if (random.nextFloat() < 1 / 128f) particleAccess.spawnExtraParticle(ParticleTypes.SNOWFLAKE, .125f); + if (random.nextFloat() < 1 / 32f) particleAccess.spawnExtraParticle(ParticleTypes.SNEEZE, .125f); + } + + @Override + public void affectEntity(Entity entity, Level level) { + if (entity instanceof LivingEntity livingEntity) { + livingEntity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 10, 0, true, true)); } } } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/kinetics/fan/processing/SnowPowderRecipe.java b/src/main/java/net/nuclearteam/createnuclear/content/kinetics/fan/processing/SnowPowderRecipe.java new file mode 100644 index 0000000..8ca555b --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/kinetics/fan/processing/SnowPowderRecipe.java @@ -0,0 +1,36 @@ +package net.nuclearteam.createnuclear.content.kinetics.fan.processing; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.content.processing.recipe.ProcessingRecipeParams; +import com.simibubi.create.content.processing.recipe.StandardProcessingRecipe; +import net.minecraft.world.item.crafting.SingleRecipeInput; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.CNRecipeTypes; + +@ParametersAreNonnullByDefault +public class SnowPowderRecipe extends StandardProcessingRecipe { + + public SnowPowderRecipe(ProcessingRecipeParams params) { + super(CNRecipeTypes.SNOW_POWDER, params); + } + + @Override + public boolean matches(SingleRecipeInput inv, Level worldIn) { + if (inv.isEmpty()) + return false; + return ingredients.get(0) + .test(inv.getItem(0)); + } + + @Override + protected int getMaxInputCount() { + return 1; + } + + @Override + protected int getMaxOutputCount() { + return 12; + } + +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/logistics/BigFluidStack.java b/src/main/java/net/nuclearteam/createnuclear/content/logistics/BigFluidStack.java new file mode 100644 index 0000000..9a7c4c9 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/logistics/BigFluidStack.java @@ -0,0 +1,108 @@ +package net.nuclearteam.createnuclear.content.logistics; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.createmod.catnip.nbt.NBTHelper; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.fluids.FluidStack; +import net.nuclearteam.createnuclear.api.ReactorFluidTypesValue; +import net.nuclearteam.createnuclear.api.multiblock.fluid.ReactorFluidType; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class BigFluidStack { + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + FluidStack.OPTIONAL_CODEC.fieldOf("fluid_stack").forGetter(s -> s.stack), + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("amount").forGetter(s -> s.amount) + ).apply(i, BigFluidStack::new)); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + FluidStack.OPTIONAL_STREAM_CODEC, s -> s.stack, + ByteBufCodecs.VAR_INT, s -> s.amount, + BigFluidStack::new + ); + + public static final int INF = 1_000_000_000; + + public FluidStack stack; + public int amount; + + public BigFluidStack(FluidStack stack) { + this(stack, 1); + } + + public BigFluidStack(FluidStack stack, int amount) { + this.stack = stack; + this.amount = amount; + } + + public CompoundTag write(HolderLookup.Provider registries) { + return (CompoundTag) CODEC.encodeStart(registries.createSerializationContext(NbtOps.INSTANCE), this) + .getOrThrow(); + } + + public static BigFluidStack read(HolderLookup.Provider registries, CompoundTag tag) { + return CODEC.parse(registries.createSerializationContext(NbtOps.INSTANCE), tag) + .getOrThrow(); + } + + public boolean isInfinite() { + return amount >= INF; + } + + public static BigFluidStack receive(RegistryFriendlyByteBuf buffer) { + return new BigFluidStack(FluidStack.STREAM_CODEC.decode(buffer), buffer.readVarInt()); + } + + public static Comparator comparator() { + return (i1, i2) -> Integer.compare(i2.amount, i1.amount); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) + return true; + if (obj instanceof BigFluidStack other) + return FluidStack.isSameFluidSameComponents(stack, other.stack) && amount == other.amount; + return false; + } + + @Override + public int hashCode() { + return (nullHash(stack) * 31) ^ Integer.hashCode(amount); + } + + int nullHash(Object o) { + return o == null ? 0 : o.hashCode(); + } + + @Override + public String toString() { + return "(" + stack.getHoverName().getString() + " x" + amount + ")"; + } + + public static List duplicateWrappers(List list) { + List copy = new ArrayList<>(); + for (BigFluidStack bigFluidStack : list) + copy.add(new BigFluidStack(bigFluidStack.stack, bigFluidStack.amount)); + return copy; + } + + public ReactorFluidType getFluidtype(@Nullable Level level) { + if (level == null) { + return ReactorFluidTypesValue.getReactorFluidType(this.stack.getFluid()); + } + return ReactorFluidType.resolveReactorFluidType(this.stack.getFluid(), level); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/CNMultiblock.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/CNMultiblock.java index e0dd7b6..aa5a500 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/CNMultiblock.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/CNMultiblock.java @@ -12,32 +12,76 @@ public class CNMultiblock { public static final MultiBlockManagerBeta REGISTRATE_MULTIBLOCK = new MultiBlockManagerBeta<>(); - public static final String AAAAA = "AAAAA"; - public static final String AABAA = "AABAA"; - public static final String ADADA = "ADADA"; - public static final String BACAB = "BACAB"; - public static final String AAIAA = "AAIAA"; - public static final String AAAA = "AA*AA"; - public static final String AAOAA = "AAOAA"; + + private static final Predicate blockInWorldAPredicate = state -> + stateIs(CNBlocks.REACTOR_CASING.get()).test(state) + || stateIs(CNBlocks.REACTOR_OUTPUT.get()).test(state) + || stateIs(CNBlocks.REACTOR_ROD_INPUT.get()).test(state) + || stateIs(CNBlocks.REACTOR_FLUID_INPUT.get()).test(state) + || stateIs(CNBlocks.REACTOR_ALARM.get()).test(state) + ; static { - REGISTRATE_MULTIBLOCK.register("createnuclear:reactor", - TypeMultiblock.REACTOR, + REGISTRATE_MULTIBLOCK.register("createnuclear:reactor5x5", + TypeMultiblock.REACTOR_T1, SimpleMultiBlockAislePatternBuilder.start() - .aisle(AAAAA, AAAAA, AAAAA, AAAAA, AAAAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AAIAA, ADADA, BACAB, ADADA, AAAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AAAAA, AAAAA, AAAAA, AAAAA, AAOAA) - .where('A', stateIs(CNBlocks.REACTOR_CASING.get())) + .aisle("OOOOO", "OAAAO", "OAAAO", "OAAAO", "OOOOO") + .aisle("OABAO", "ADDDA", "BDCDB", "ADDDA", "OABAO") + .aisle("OABAO", "ADDDA", "BDCDB", "ADDDA", "OABAO") + .aisle("OABAO", "ADDDA", "BDCDB", "ADDDA", "OA*AO") + .aisle("OABAO", "ADDDA", "BDCDB", "ADDDA", "OABAO") + .aisle("OABAO", "ADDDA", "BDCDB", "ADDDA", "OABAO") + .aisle("OOOOO", "OAAAO", "OAAAO", "OAAAO", "OOOOO") + .where('A', blockInWorldAPredicate) .where('B', stateIs(CNBlocks.REACTOR_FRAME.get())) .where('C', stateIs(CNBlocks.REACTOR_CORE.get())) .where('D', stateIs(CNBlocks.REACTOR_COOLER.get())) .where('*', stateIs(CNBlocks.REACTOR_CONTROLLER.get())) - .where('O', stateIs(CNBlocks.REACTOR_OUTPUT.get())) - .where('I', stateIs(CNBlocks.REACTOR_INPUT.get())) + .where('O', stateIs(CNBlocks.REACTOR_CASING.get())) + .build() + ); + + REGISTRATE_MULTIBLOCK.register("createnuclear:reactor7x7", + TypeMultiblock.REACTOR_T2, + SimpleMultiBlockAislePatternBuilder.start() + .aisle("OOOOOOO", "OAAAAAO", "OAAAAAO", "OAAAAAO", "OAAAAAO", "OAAAAAO", "OOOOOOO") + .aisle("OABABAO", "ADDDDDA", "BDCDCDB", "ADDDDDA", "BDCDCDB", "ADDDDDA", "OABABAO") + .aisle("OABABAO", "ADDDDDA", "BDCDCDB", "ADDDDDA", "BDCDCDB", "ADDDDDA", "OABABAO") + .aisle("OABABAO", "ADDDDDA", "BDCDCDB", "ADDDDDA", "BDCDCDB", "ADDDDDA", "OABABAO") + .aisle("OABABAO", "ADDDDDA", "BDCDCDB", "ADDDDDA", "BDCDCDB", "ADDDDDA", "OAB*BAO") + .aisle("OABABAO", "ADDDDDA", "BDCDCDB", "ADDDDDA", "BDCDCDB", "ADDDDDA", "OABABAO") + .aisle("OABABAO", "ADDDDDA", "BDCDCDB", "ADDDDDA", "BDCDCDB", "ADDDDDA", "OABABAO") + .aisle("OABABAO", "ADDDDDA", "BDCDCDB", "ADDDDDA", "BDCDCDB", "ADDDDDA", "OABABAO") + .aisle("OOOOOOO", "OAAAAAO", "OAAAAAO", "OAAAAAO", "OAAAAAO", "OAAAAAO", "OOOOOOO") + .where('A', blockInWorldAPredicate) + .where('B', a -> a.getState().is(CNBlocks.REACTOR_FRAME.get())) + .where('C', a -> a.getState().is(CNBlocks.REACTOR_CORE.get())) + .where('D', a -> a.getState().is(CNBlocks.REACTOR_COOLER.get())) + .where('*', a -> a.getState().is(CNBlocks.REACTOR_CONTROLLER.get())) + .where('O', a -> a.getState().is(CNBlocks.REACTOR_CASING.get())) + .build() + ); + + REGISTRATE_MULTIBLOCK.register("createnuclear:reactor9x9", + TypeMultiblock.REACTOR_T3, + SimpleMultiBlockAislePatternBuilder.start() + .aisle("OOOOOOOOO", "OAAAAAAAO", "OAAAAAAAO", "OAAAAAAAO", "OAAAAAAAO", "OAAAAAAAO", "OAAAAAAAO", "OAAAAAAAO", "OOOOOOOOO") + .aisle("OBAABAABO", "BDDDDDDDB", "ADCDCDCDA", "ADDDDDDDA", "BDCDCDCDB", "ADDDDDDDA", "ADCDCDCDA", "BDDDDDDDB", "OBAABAABO") + .aisle("OBAABAABO", "BDDDDDDDB", "ADCDCDCDA", "ADDDDDDDA", "BDCDCDCDB", "ADDDDDDDA", "ADCDCDCDA", "BDDDDDDDB", "OBAABAABO") + .aisle("OBAABAABO", "BDDDDDDDB", "ADCDCDCDA", "ADDDDDDDA", "BDCDCDCDB", "ADDDDDDDA", "ADCDCDCDA", "BDDDDDDDB", "OBAABAABO") + .aisle("OBAABAABO", "BDDDDDDDB", "ADCDCDCDA", "ADDDDDDDA", "BDCDCDCDB", "ADDDDDDDA", "ADCDCDCDA", "BDDDDDDDB", "OBAABAABO") + .aisle("OBAABAABO", "BDDDDDDDB", "ADCDCDCDA", "ADDDDDDDA", "BDCDCDCDB", "ADDDDDDDA", "ADCDCDCDA", "BDDDDDDDB", "OBAA*AABO") + .aisle("OBAABAABO", "BDDDDDDDB", "ADCDCDCDA", "ADDDDDDDA", "BDCDCDCDB", "ADDDDDDDA", "ADCDCDCDA", "BDDDDDDDB", "OBAABAABO") + .aisle("OBAABAABO", "BDDDDDDDB", "ADCDCDCDA", "ADDDDDDDA", "BDCDCDCDB", "ADDDDDDDA", "ADCDCDCDA", "BDDDDDDDB", "OBAABAABO") + .aisle("OBAABAABO", "BDDDDDDDB", "ADCDCDCDA", "ADDDDDDDA", "BDCDCDCDB", "ADDDDDDDA", "ADCDCDCDA", "BDDDDDDDB", "OBAABAABO") + .aisle("OBAABAABO", "BDDDDDDDB", "ADCDCDCDA", "ADDDDDDDA", "BDCDCDCDB", "ADDDDDDDA", "ADCDCDCDA", "BDDDDDDDB", "OBAABAABO") + .aisle("OOOOOOOOO", "OAAAAAAAO", "OAAAAAAAO", "OAAAAAAAO", "OAAAAAAAO", "OAAAAAAAO", "OAAAAAAAO", "OAAAAAAAO", "OOOOOOOOO") + .where('A', blockInWorldAPredicate) + .where('B', a -> a.getState().is(CNBlocks.REACTOR_FRAME.get())) + .where('C', a -> a.getState().is(CNBlocks.REACTOR_CORE.get())) + .where('D', a -> a.getState().is(CNBlocks.REACTOR_COOLER.get())) + .where('*', a -> a.getState().is(CNBlocks.REACTOR_CONTROLLER.get())) + .where('O', a -> a.getState().is(CNBlocks.REACTOR_CASING.get())) .build() ); } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/IHeat.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/IHeat.java index bf56b3f..fe17625 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/IHeat.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/IHeat.java @@ -1,15 +1,19 @@ package net.nuclearteam.createnuclear.content.multiblock; import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.logistics.BigItemStack; import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.utility.CreateLang; import net.createmod.catnip.lang.Lang; import net.createmod.catnip.lang.LangBuilder; import net.minecraft.ChatFormatting; import net.minecraft.world.item.ItemStack; -import net.nuclearteam.createnuclear.CNTags.CNItemTags; +import net.minecraft.world.level.Level; import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType.TypeRodPredicate; import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; +import net.nuclearteam.createnuclear.infrastructure.config.CReactorHeat; public interface IHeat extends IWrenchable { enum HeatLevel { @@ -53,21 +57,38 @@ public int getHeatValue() { }; } - public static HeatLevel of(int heat) { + public static HeatLevel of(int heat, int reactorSize) { if (heat < 0) return NONE; heat = Math.abs(heat); - if (heat > 0 && heat < 500) return SAFETY; - if (heat >= 501 && heat <= 800) return CAUTION; - if (heat >= 801 && heat <= 1000) return WARNING; - if (heat >= 1001) return DANGER; + CReactorHeat config = CNConfigs.server().reactorHeat; + int danger; + + switch (reactorSize) { + case 5 -> danger = config.size5Danger.get(); + case 7 -> danger = config.size7Danger.get(); + case 9 -> danger = config.size9Danger.get(); + default -> danger = config.size5Danger.get(); + } + + int caution = (int) (danger * 0.75); + int warning = (int) (danger * 0.90); + + if (heat > 0 && heat < caution) return SAFETY; + if (heat >= caution && heat < warning) return CAUTION; + if (heat >= warning && heat <= danger) return WARNING; + if (heat > danger) return DANGER; return NONE; } - public static LangBuilder getFormattedHeatText(int heat) { - HeatLevel heatLevel = of(heat); + public static boolean isNotDanger(int heat, int reactorSize) { + return of(heat, reactorSize) != DANGER; + } + + public static LangBuilder getFormattedHeatText(int heat, int reactorSize) { + HeatLevel heatLevel = of(heat, reactorSize); LangBuilder builder = CreateLang.builder(CreateNuclear.MOD_ID).text(TooltipHelper.makeProgressBar(5, heatLevel.ordinal()+1)); builder.translate("tooltip.heatLevel." + Lang.asId(heatLevel.name())) @@ -85,28 +106,24 @@ public static LangBuilder getFormattedHeatText(int heat) { return builder; } - public static LangBuilder getFormattedItemText(ItemStack itemRod, Boolean IsEmpty) { + public static LangBuilder getFormattedItemText(ItemStack itemRod, Boolean isEmpty, Level level) { LangBuilder builder = Lang.builder(CreateNuclear.MOD_ID); - String tooltip = "unknown"; - - if (itemRod.is(CNItemTags.FUEL.tag)) { - tooltip = "uranium"; - } - - if (itemRod.is(CNItemTags.COOLER.tag)) { - tooltip = "graphene"; - } + String tooltip = TypeRodPredicate.tooltipKey(itemRod, level); builder.translate("tooltip.item." + tooltip + ".rod") - // when it's empty, we show the number minus one to display zero because we fake the item count as 1 - .add(CreateNuclearLang.number(Math.abs((IsEmpty ? itemRod.getCount() - 1 : itemRod.getCount())))) - .style(ChatFormatting.BLUE) + // when it's empty, we show the number minus one to display zero because we fake the item count as 1 + .add(CreateNuclearLang.number(Math.abs((isEmpty ? itemRod.getCount() - 1 : itemRod.getCount())))) + .style(ChatFormatting.BLUE) ; return builder; } + public static LangBuilder getFormattedItemText(BigItemStack itemRod, Boolean isEmpty, Level level) { + return getFormattedItemText(new ItemStack(itemRod.stack.getItem(), itemRod.count), isEmpty, level); + } + public static LangBuilder getName(String name) { LangBuilder builder = CreateNuclearLang.builder(CreateNuclear.MOD_ID); builder.translate("gui." + name + ".info_header.title"); @@ -114,4 +131,4 @@ public static LangBuilder getName(String name) { return builder; } } -} +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/MultiblockHelpers.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/MultiblockHelpers.java new file mode 100644 index 0000000..f168e39 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/MultiblockHelpers.java @@ -0,0 +1,63 @@ +package net.nuclearteam.createnuclear.content.multiblock; + +import net.minecraft.world.entity.LivingEntity; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.content.multiblock.pattern.ReactorPattern; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancementBehaviour; +import org.jetbrains.annotations.Nullable; + +import java.util.function.BiConsumer; + +public class MultiblockHelpers { + private static final ReactorPattern pattern = new ReactorPattern(); + + /** + * Utility helpers for handling multiblock placement and removal events. + * These helpers locate the controller for a given part position and + * invoke provided callbacks to register or remove parts. + */ + public static void handleOnPlace(BlockPos pos, Level level, BiConsumer register) { + BlockPos controllerPos = pattern.findControllerPos(pos, level, true); + if (controllerPos != null) { + ReactorControllerBlockEntity controllerBlockEntity = (ReactorControllerBlockEntity) level.getBlockEntity(controllerPos); + if (controllerBlockEntity != null) { + register.accept(controllerBlockEntity, pos); + } + } + } + + public static void handleRemoval(BlockPos pos, Level level, BiConsumer remover) { + BlockPos controllerPos = pattern.findControllerPos(pos, level, false); + if (controllerPos != null) { + ReactorControllerBlockEntity controllerBlockEntity = (ReactorControllerBlockEntity) level.getBlockEntity(controllerPos); + if (controllerBlockEntity != null) { + remover.accept(controllerBlockEntity, pos); + } + } + } + + public static ReactorControllerBlockEntity getControllerForPart(Level level, BlockPos pos) { + /** + * Returns the controller entity for the given part position, or null + * if no valid controller is found. + */ + BlockPos controllerPos = pattern.findControllerPos(pos, level); + if (controllerPos != null) { + return (ReactorControllerBlockEntity) level.getBlockEntity(controllerPos); + } + + return null; + } + + public static void handleAdvancedPlacedBy(BlockPos pos, Level level, @Nullable LivingEntity entity) { + if (entity == null) return; + + ReactorControllerBlockEntity controller = getControllerForPart(level, pos); + + if (controller != null) { + CNAdvancementBehaviour.setPlacedBy(level, controller.getBlockPos(), entity); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/ReactorAssembler.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/ReactorAssembler.java new file mode 100644 index 0000000..a591c5f --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/ReactorAssembler.java @@ -0,0 +1,199 @@ +package net.nuclearteam.createnuclear.content.multiblock; + +import net.createmod.catnip.lang.LangBuilder; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.CNSoundEvents; +import net.nuclearteam.createnuclear.api.multiblock.BlockPattern; +import net.nuclearteam.createnuclear.api.multiblock.TypeMultiblock; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.content.multiblock.frame.ReactorFrameEntity; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.ReactorFluidInputEntity; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancement; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; +import net.nuclearteam.createnuclear.foundation.utility.NotifyUtil; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; + +import java.util.ArrayList; +import java.util.List; + +public final class ReactorAssembler { + + public static final int configRadius = CNConfigs.server().notify.warningDistance.get(); + public static final boolean configWarnAll = CNConfigs.server().notify.warnAllPlayers.get(); + + private ReactorAssembler() {} + + public static void assemble(BlockPos pos, Level level) { + if (level.isClientSide) return; + + ReactorControllerBlockEntity entity = getBlockEntity(level, pos); + if (entity == null) return; + + BlockPattern result = CNMultiblock.REGISTRATE_MULTIBLOCK.findStructure(level, pos, entity); + if (result == null) return; + + // Captured before setAssembled(true) below: assemble() is also reached from + // ReactorPattern.findControllerPos on an already-assembled reactor, and only the + // actual not-assembled -> assembled transition should notify and play the cue. + boolean wasAssembled = entity.isAssembled(); + + sendMessageToPlayer(level, pos, CreateNuclearLang.translate("notification.reactor.assembled"), !wasAssembled); + + if (!wasAssembled) { + // Server-side (null player) so the one-shot broadcasts to nearby clients. + level.playSound(null, pos, CNSoundEvents.MOTOR_ASSEMBLE.getMainEvent(), SoundSource.BLOCKS, 1.0f, 1.0f); + } + + switch (result.data()) { + case REACTOR_T1 -> entity.getAdvancement().awardPlayer(CNAdvancement.T1_REACTOR); + case REACTOR_T2 -> entity.getAdvancement().awardPlayer(CNAdvancement.T2_REACTOR); + case REACTOR_T3 -> entity.getAdvancement().awardPlayer(CNAdvancement.T3_REACTOR); + } + + entity.setMultiblockSize(result.data().getSize()); + entity.setAssembled(true); + entity.setMultiblockStructure(ReactorAssembler.getStructureBound(pos, entity.getMultiblockSize(), entity.getMultiblockFacing())); + + findAndRegisterSpecialBlocks(entity.getMultiblockPos(), entity, level); + } + + public static void disassemble(BlockPos pos, Level level) { + if (level.isClientSide) return; + + ReactorControllerBlockEntity entity = getBlockEntity(level, pos); + if (entity == null || !entity.isAssembled()) return; + + BlockPattern result = CNMultiblock.REGISTRATE_MULTIBLOCK.findStructure(level, pos, entity); + if (result != null) return; + + sendMessageToPlayer(level, pos, CreateNuclearLang.translate("notification.reactor.disassembled"), true); + + // Both early returns above already guarantee this is a real assembled -> broken + // transition, so no extra guard is needed here. + level.playSound(null, pos, CNSoundEvents.MOTOR_DISASSEMBLE.getMainEvent(), SoundSource.BLOCKS, 1.0f, 1.0f); + + entity.setAssembled(false); + entity.removeIOAll(); + } + + public static void findAndRegisterSpecialBlocks(BoundingBox reactorPos, ReactorControllerBlockEntity entity, Level level) { + int xMin = reactorPos.minX(), xMax = reactorPos.maxX(); + int yMin = reactorPos.minY(), yMax = reactorPos.maxY(); + int zMin = reactorPos.minZ(), zMax = reactorPos.maxZ(); + + final Block reactorOutputBlock = CNBlocks.REACTOR_OUTPUT.get(); + final Block reactorRodInputBlock = CNBlocks.REACTOR_ROD_INPUT.get(); + final Block reactorInputFluidBlock = CNBlocks.REACTOR_FLUID_INPUT.get(); + final Block reactorAlarmBlock = CNBlocks.REACTOR_ALARM.get(); + final Block reactorFrameBlock = CNBlocks.REACTOR_FRAME.get(); + + BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos(); + + int frameMinY = Integer.MAX_VALUE; + int frameMaxY = Integer.MIN_VALUE; + + // Collected here and assigned their capacity after the scan: the reactor-size capacity is a + // single TOTAL shared across every fluid input, so we split it once we know how many there are. + List fluidInputs = new ArrayList<>(); + + for (int y = yMin; y <= yMax; y++) { + boolean isYBoundary = (y == yMin || y == yMax); + for (int x = xMin; x <= xMax; x++) { + boolean isXBoundary = (x == xMin || x == xMax); + for (int z = zMin; z <= zMax; z++) { + boolean isZBoundary = (z == zMin || z == zMax); + + if (!(isYBoundary || isXBoundary || isZBoundary)) continue; + + mutablePos.set(x, y, z); + BlockState blockState = level.getBlockState(mutablePos); + + if (blockState.is(reactorOutputBlock)) { + entity.addOutput(mutablePos.immutable()); + } else if (blockState.is(reactorRodInputBlock)) { + entity.addInput(mutablePos.immutable()); + } else if (blockState.is(reactorInputFluidBlock)) { + entity.addInputFluid(mutablePos.immutable()); + if (level.getBlockEntity(mutablePos) instanceof ReactorFluidInputEntity fluidInput) { + fluidInputs.add(fluidInput); + } + } else if (blockState.is(reactorAlarmBlock)) { + entity.addAlarm(mutablePos.immutable()); + } else if (blockState.is(reactorFrameBlock)) { + if (level.getBlockEntity(mutablePos) instanceof ReactorFrameEntity frame) { + frame.setController(entity.getBlockPos()); + } + frameMinY = Math.min(frameMinY, y); + frameMaxY = Math.max(frameMaxY, y); + } + } + } + } + + if (frameMinY != Integer.MAX_VALUE) { + entity.getFrameDisplayManager().setFrameColumn(frameMinY, frameMaxY, entity::notifyUpdate); + } + + distributeFluidInputCapacity(fluidInputs, entity.getMultiblockSize()); + } + + /** + * Splits the reactor-size total fluid capacity evenly across all fluid inputs so the combined + * max capacity always equals the configured value, regardless of how many inputs were placed. + * The integer remainder is spread one unit at a time over the first inputs so the sum stays exact. + */ + private static void distributeFluidInputCapacity(List fluidInputs, int reactorSize) { + int count = fluidInputs.size(); + if (count == 0) return; + + int total = ReactorFluidInputEntity.getCapacityForReactorSize(reactorSize); + int base = total / count; + int remainder = total % count; + + for (int i = 0; i < count; i++) { + fluidInputs.get(i).applyCapacity(base + (i < remainder ? 1 : 0)); + } + } + + private static ReactorControllerBlockEntity getBlockEntity(Level level, BlockPos pos) { + if (level.getBlockEntity(pos) instanceof ReactorControllerBlockEntity entity) { + return entity; + } + return null; + } + + private static void sendMessageToPlayer(Level level, BlockPos pos, LangBuilder component, boolean condition) { + if (!condition) return; + + NotifyUtil.sendActionBar(level, pos, + component, + ChatFormatting.GOLD, configRadius, configWarnAll + ); + } + + public static BoundingBox getStructureBound(BlockPos center, int size, Direction facing) { + int radius = (size - 1) / 2; + int height = radius + 1; + int depth = size - 1; + Direction into = facing.getOpposite(); + + int axisX = into.getStepX() * depth; + int axisZ = into.getStepZ() * depth; + + int minX = center.getX() + Math.min(0, axisX) - (axisX == 0 ? radius : 0); + int maxX = center.getX() + Math.max(0, axisX) + (axisX == 0 ? radius : 0); + int minZ = center.getZ() + Math.min(0, axisZ) - (axisZ == 0 ? radius : 0); + int maxZ = center.getZ() + Math.max(0, axisZ) + (axisZ == 0 ? radius : 0); + + return new BoundingBox(minX, center.getY() - height, minZ, + maxX, center.getY() + height, maxZ); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/alarm/ReactorAlarm.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/alarm/ReactorAlarm.java new file mode 100644 index 0000000..a8d9eed --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/alarm/ReactorAlarm.java @@ -0,0 +1,84 @@ +package net.nuclearteam.createnuclear.content.multiblock.alarm; + +import com.simibubi.create.foundation.block.IBE; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.nuclearteam.createnuclear.CNBlockEntityTypes; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.content.multiblock.pattern.ReactorPattern; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancementBehaviour; + +import javax.annotation.Nullable; + +public class ReactorAlarm extends Block implements IBE { + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + protected ReactorPattern pattern = new ReactorPattern(); + + public ReactorAlarm(Properties props) { + super(props); + this.registerDefaultState(this.defaultBlockState().setValue(POWERED, false)); + } + + // Registers this alarm with the multiblock controller when placed + @Override + public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, level, pos, oldState, isMoving); + MultiblockHelpers.handleOnPlace(pos, level, ReactorControllerBlockEntity::addAlarm); + } + + @Override + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity pPlacer, ItemStack stack) { + super.setPlacedBy(level, pos, state, pPlacer, stack); + MultiblockHelpers.handleAdvancedPlacedBy(pos, level, pPlacer); + } + + // Unregisters this alarm from the multiblock controller on removal (piston, explosion, etc.) + @Override + public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { + if (!state.is(newState.getBlock())) { + MultiblockHelpers.handleRemoval(pos, level, ReactorControllerBlockEntity::removeAlarm); + super.onRemove(state, level, pos, newState, isMoving); + } + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + return this.defaultBlockState().setValue(POWERED, ctx.getLevel().hasNeighborSignal(ctx.getClickedPos())); + } + + @Override + public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { + if (level.isClientSide) return; + boolean poweredNow = level.hasNeighborSignal(pos); + if (state.getValue(POWERED) != poweredNow) { + level.setBlock(pos, state.setValue(POWERED, poweredNow), 3); + } + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(POWERED); + } + + @Override + public Class getBlockEntityClass() { + return ReactorAlarmEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return CNBlockEntityTypes.REACTOR_ALARM.get(); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/alarm/ReactorAlarmEntity.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/alarm/ReactorAlarmEntity.java new file mode 100644 index 0000000..3348e40 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/alarm/ReactorAlarmEntity.java @@ -0,0 +1,101 @@ +package net.nuclearteam.createnuclear.content.multiblock.alarm; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.nuclearteam.createnuclear.CNSoundEvents; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancement; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancementBehaviour; + +import java.util.List; + +public class ReactorAlarmEntity extends SmartBlockEntity { + + public ReactorControllerBlockEntity controller = null; + private CNAdvancementBehaviour advancement; + private boolean advancementAwarded = false; // Prevents repeatedly awarding the advancement on every tick + + @OnlyIn(Dist.CLIENT) + protected ReactorAlarmSoundInstance soundInstance; + + public ReactorAlarmEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void tick() { + super.tick(); + if (level == null || !(getBlockState().getBlock() instanceof ReactorAlarm)) return; + + if (level.isClientSide) { + tickAudio(); // DistExecutor is unnecessary here; the level-side check is enough and avoids thread overhead + } else { + tickServer(); + } + } + + @OnlyIn(Dist.CLIENT) + protected void tickAudio() { + BlockState state = getBlockState(); + boolean powered = state.hasProperty(ReactorAlarm.POWERED) && state.getValue(ReactorAlarm.POWERED); + + if (!powered) { + stopSound(); + return; + } + + if (soundInstance == null || soundInstance.isStopped()) { + Minecraft minecraft = Minecraft.getInstance(); + try { + soundInstance = new ReactorAlarmSoundInstance(level, worldPosition, CNSoundEvents.REACTOR_ALARM_LOOP.getMainEvent()); + minecraft.getSoundManager().play(soundInstance); + } catch (Exception e) { + CreateNuclear.LOGGER.warn("Failed to start alarm sound: " + e.getMessage()); + } + } + } + + @OnlyIn(Dist.CLIENT) + private void stopSound() { + if (soundInstance != null) { + try { + soundInstance.fadeOut(); + } catch (Exception e) { + CreateNuclear.LOGGER.warn("Error while stopping the sound: " + e.getMessage()); + } + soundInstance = null; + } + } + + private void tickServer() { + BlockState state = getBlockState(); + if (!(state.getBlock() instanceof ReactorAlarm)) return; + + boolean powered = state.getValue(ReactorAlarm.POWERED); + + if (powered) { + if (!advancementAwarded) { // Award it only once, on the rising edge + this.advancement.awardPlayer(CNAdvancement.SILENCE_THE_CORE); + advancementAwarded = true; + } + } else { + advancementAwarded = false; // Reset when the alarm turns off + } + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(advancement = new CNAdvancementBehaviour(this, CNAdvancement.SILENCE_THE_CORE)); + } + + public void setController(ReactorControllerBlockEntity controller) { + this.controller = controller; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/alarm/ReactorAlarmSoundInstance.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/alarm/ReactorAlarmSoundInstance.java new file mode 100644 index 0000000..04793cd --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/alarm/ReactorAlarmSoundInstance.java @@ -0,0 +1,50 @@ +package net.nuclearteam.createnuclear.content.multiblock.alarm; + +import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance; +import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.nuclearteam.createnuclear.CreateNuclear; + +public class ReactorAlarmSoundInstance extends AbstractTickableSoundInstance { + private final BlockPos pos; + private final Level level; + + public ReactorAlarmSoundInstance(Level level, BlockPos pos, SoundEvent sound) { + super(sound, SoundSource.BLOCKS, level != null ? level.random : null); + this.level = level; + this.pos = pos; + if (pos != null) { + this.x = pos.getX(); + this.y = pos.getY(); + this.z = pos.getZ(); + } + this.looping = true; + this.delay = 0; + this.volume = 10F; + } + + @Override + public void tick() { + try { + if (level == null || pos == null) { + stop(); + return; + } + + BlockState state = level.getBlockState(pos); + if (!(state.getBlock() instanceof ReactorAlarm)) { + stop(); + } + } catch (Exception e) { + stop(); + CreateNuclear.LOGGER.warn(e.getMessage()); + } + } + + public void fadeOut() { + stop(); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/PatternData.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/PatternData.java index aefbe4c..9aa7e6e 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/PatternData.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/PatternData.java @@ -1,36 +1,41 @@ package net.nuclearteam.createnuclear.content.multiblock.bluePrintItem; import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.world.item.ItemStack; -import net.nuclearteam.createnuclear.CNTags.CNItemTags; public record PatternData(int slot, ItemStack stack) { private static final ItemStack DEFAULT_STACK = ItemStack.EMPTY; + + /** + * Uses {@link ItemStack#OPTIONAL_CODEC}, not {@link ItemStack#CODEC}: a reactor pattern is 57 + * slots and is almost never full, and {@code ItemStack.CODEC} refuses the empty stack + * ("Item must not be minecraft:air" / "Value must be within range [1;99]: 0"). With the strict + * codec, any blueprint sitting in a controller made the block entity throw at chunk-save time, + * so the controller silently lost its blueprint on every world reload. + *

+ * The encoding of non-empty stacks is identical between the two codecs: only the empty stack + * changes, from "rejected" to {@code {}}, so blueprints already on disk still load. + */ public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( - Codec.INT.fieldOf("slot").forGetter(PatternData::slot), - ItemStack.CODEC - .flatXmap(stack -> { - if (!stack.isEmpty() || stack.is(CNItemTags.FUEL.tag) || stack.is(CNItemTags.COOLER.tag)) return DataResult.success(stack); - return DataResult.success(DEFAULT_STACK); - }, - DataResult::success - ) - .fieldOf("Stack") - .forGetter(PatternData::stack) - ).apply(i, PatternData::new) - ); + Codec.INT.fieldOf("slot").forGetter(PatternData::slot), + ItemStack.OPTIONAL_CODEC.fieldOf("Stack").forGetter(PatternData::stack) + ).apply(i, PatternData::new)); - public static final StreamCodec STREAM_CODEC = - StreamCodec.composite( - ByteBufCodecs.INT, PatternData::slot, - ItemStack.STREAM_CODEC, PatternData::stack, - PatternData::new - ); + /** + * Uses {@link ItemStack#OPTIONAL_STREAM_CODEC} for the same reason as {@link #CODEC}: + * {@code ItemStack.STREAM_CODEC} throws {@code EncoderException("Empty ItemStack not allowed")} + * on the empty stack, and this component is {@code networkSynchronized}, so an unfilled pattern + * failed to encode as soon as the blueprint was sent to a client. + */ + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.INT, PatternData::slot, + ItemStack.OPTIONAL_STREAM_CODEC, PatternData::stack, + PatternData::new + ); public static ItemStack getDefaultStack() { return DEFAULT_STACK; diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintData.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintData.java index a1b39c5..d51e37e 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintData.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintData.java @@ -6,12 +6,18 @@ import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType.TypeRodPredicate; import java.util.Arrays; import java.util.List; import java.util.Objects; -public record ReactorBluePrintData(int countGraphiteRod, int countUraniumRod, int graphiteTime, int uraniumTime, PatternData[] pattern, PatternData[] patternAll) { +public record ReactorBluePrintData(int countCooledRod, int countFuelRod, PatternData[] pattern) { + public static final ReactorBluePrintData EMPTY = new ReactorBluePrintData(0, 0, new PatternData[0]); + private static final Codec PATTERN_ARRAY_CODEC = PatternData.CODEC.listOf().xmap( list -> list.toArray(PatternData[]::new), List::of @@ -20,44 +26,51 @@ public record ReactorBluePrintData(int countGraphiteRod, int countUraniumRod, in private static final StreamCodec STREAM_PATTERN_ARRAY_CODEC = CatnipStreamCodecBuilders.array(PatternData.STREAM_CODEC, PatternData.class); public static final Codec CODEC = RecordCodecBuilder.create(instance -> - instance.group( - Codec.INT.fieldOf("countGraphiteRod").forGetter(ReactorBluePrintData::countGraphiteRod), - Codec.INT.fieldOf("countUraniumRod").forGetter(ReactorBluePrintData::countUraniumRod), - Codec.INT.fieldOf("graphiteTime").forGetter(ReactorBluePrintData::graphiteTime), - Codec.INT.fieldOf("uraniumTime").forGetter(ReactorBluePrintData::uraniumTime), - PATTERN_ARRAY_CODEC.fieldOf("pattern").forGetter(ReactorBluePrintData::pattern), - PATTERN_ARRAY_CODEC.fieldOf("patternAll").forGetter(ReactorBluePrintData::patternAll) - ).apply(instance, ReactorBluePrintData::new) + instance.group( + Codec.INT.fieldOf("countCooledRod").forGetter(ReactorBluePrintData::countCooledRod), + Codec.INT.fieldOf("countFuelRod").forGetter(ReactorBluePrintData::countFuelRod), + PATTERN_ARRAY_CODEC.fieldOf("pattern").forGetter(ReactorBluePrintData::pattern) + ).apply(instance, ReactorBluePrintData::new) ); public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.INT, ReactorBluePrintData::countGraphiteRod, - ByteBufCodecs.INT, ReactorBluePrintData::countUraniumRod, - ByteBufCodecs.INT, ReactorBluePrintData::graphiteTime, - ByteBufCodecs.INT, ReactorBluePrintData::uraniumTime, + ByteBufCodecs.INT, ReactorBluePrintData::countCooledRod, + ByteBufCodecs.INT, ReactorBluePrintData::countFuelRod, STREAM_PATTERN_ARRAY_CODEC, ReactorBluePrintData::pattern, - STREAM_PATTERN_ARRAY_CODEC, ReactorBluePrintData::patternAll, ReactorBluePrintData::new ); + /** + * Normalized view of {@link #pattern()}. Recomputed on demand, never stored. + */ + public PatternData[] patternAll(Level level) { + PatternData[] result = new PatternData[pattern().length]; + ItemStack glassPane = new ItemStack(Items.GLASS_PANE); + + for (int i = 0; i < pattern().length; i++) { + ItemStack stack = pattern()[i].stack(); + boolean isRods = TypeRodPredicate.isFuel(stack, level) || TypeRodPredicate.isCooled(stack, level); + + result[i] = new PatternData(i, isRods ? stack : glassPane); + } + + return result; + } + @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof ReactorBluePrintData that)) return false; - - return countGraphiteRod == that.countGraphiteRod - && countUraniumRod == that.countUraniumRod - && graphiteTime == that.graphiteTime - && uraniumTime == that.uraniumTime - && Arrays.equals(pattern, that.pattern) - && Arrays.equals(patternAll, that.patternAll); + if (!(o instanceof ReactorBluePrintData(int cooledRod, int fuelRod, PatternData[] pattern1))) return false; + + return countCooledRod == cooledRod + && countFuelRod == fuelRod + && Arrays.equals(pattern, pattern1); } @Override public int hashCode() { - int result = Objects.hash(countGraphiteRod, countUraniumRod, graphiteTime, uraniumTime); + int result = Objects.hash(countCooledRod, countFuelRod); result = 31 * result + Arrays.hashCode(pattern); - result = 31 * result + Arrays.hashCode(patternAll); return result; } } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItem.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItem.java index 956f447..38debf8 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItem.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItem.java @@ -1,10 +1,10 @@ package net.nuclearteam.createnuclear.content.multiblock.bluePrintItem; -import com.simibubi.create.AllDataComponents; -import com.simibubi.create.foundation.item.ItemHelper; +import net.minecraft.ChatFormatting; import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -15,16 +15,15 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.neoforged.neoforge.items.ItemStackHandler; -import net.nuclearteam.createnuclear.CNDamageTypes; import net.nuclearteam.createnuclear.CNDataComponents; import net.nuclearteam.createnuclear.CNItems; import org.jetbrains.annotations.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.Arrays; import java.util.List; @ParametersAreNonnullByDefault @@ -35,6 +34,19 @@ public ReactorBluePrintItem(Properties properties) { super(properties); } + + @Override + public void appendHoverText(ItemStack stack, TooltipContext context, List tooltipComponents, TooltipFlag tooltipFlag) { + super.appendHoverText(stack, context, tooltipComponents, tooltipFlag); + + tooltipComponents.add(Component.translatable("item.createnuclear.reactor_blueprint.tooltip") + .withStyle(ChatFormatting.GRAY)); + + // Adjust the tooltip text to hint at the available action + tooltipComponents.add(Component.translatable("item.createnuclear.reactor_blueprint.tooltip_hint") + .withStyle(ChatFormatting.DARK_GRAY)); + } + @Override public Component getDisplayName() { return Component.translatable("reactor.item.gui.name"); @@ -57,18 +69,26 @@ public InteractionResult useOn(UseOnContext context) { public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { ItemStack heldItem = player.getItemInHand(hand); + // Plain right-click -> Opens the Blueprint screen if (!player.isShiftKeyDown() && hand == InteractionHand.MAIN_HAND) { if (!world.isClientSide && player instanceof ServerPlayer) - player.openMenu(this, buf -> { - ItemStack.STREAM_CODEC.encode(buf, heldItem); - }); + player.openMenu(this, buf -> ItemStack.STREAM_CODEC.encode(buf, heldItem)); return InteractionResultHolder.success(heldItem); } + // Shift + right-click -> Sends a clickable link in chat! else if (player.isShiftKeyDown() && hand == InteractionHand.MAIN_HAND) { - if (!world.isClientSide && player instanceof ServerPlayer) { - player.openMenu(this, buf -> { - ItemStack.STREAM_CODEC.encode(buf, heldItem); - }); + if (!world.isClientSide) { + MutableComponent message = Component.translatable("item.createnuclear.reactor_blueprint.chat_info") + .withStyle(ChatFormatting.GREEN) + .append(" ") + .append(Component.translatable("item.createnuclear.reactor_blueprint.wiki_link") + .withStyle(style -> style + .withColor(ChatFormatting.AQUA) + .withUnderlined(true) + .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://wiki.createnuclear.net/")) + )); + + player.sendSystemMessage(message); } return InteractionResultHolder.success(heldItem); } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItemPacket.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItemPacket.java deleted file mode 100644 index 7e163d7..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItemPacket.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.nuclearteam.createnuclear.content.multiblock.bluePrintItem; - -import io.netty.buffer.ByteBuf; -import net.createmod.catnip.codecs.stream.CatnipStreamCodecBuilders; -import net.createmod.catnip.codecs.stream.CatnipStreamCodecs; -import net.createmod.catnip.net.base.ServerboundPacketPayload; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.server.level.ServerPlayer; -import net.nuclearteam.createnuclear.CNPackets; -import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; - -public record ReactorBluePrintItemPacket(CompoundTag tag, float heat, int graphiteTime, int uraniumTime, int countGraphiteRod, int countUraniumRod) implements ServerboundPacketPayload { - - public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.COMPOUND_TAG, ReactorBluePrintItemPacket::tag, - ByteBufCodecs.FLOAT, ReactorBluePrintItemPacket::heat, - ByteBufCodecs.INT, ReactorBluePrintItemPacket::graphiteTime, - ByteBufCodecs.INT, ReactorBluePrintItemPacket::uraniumTime, - ByteBufCodecs.INT, ReactorBluePrintItemPacket::countGraphiteRod, - ByteBufCodecs.INT, ReactorBluePrintItemPacket::countUraniumRod, - ReactorBluePrintItemPacket::new - ); - - @Override - public PacketTypeProvider getTypeProvider() { - return CNPackets.CONFIGURE_REACTOR_PATTERN; - } - - @Override - public void handle(ServerPlayer player) { - if (player.containerMenu instanceof ReactorBluePrintMenu c) { - // On crée directement le state et on l’applique - this.applyState(new ReactorState( - this.countUraniumRod, - this.countGraphiteRod, - this.graphiteTime, - this.uraniumTime, - this.heat - ), c); - } - } - - public record ReactorState( - int countUraniumRod, - int countGraphiteRod, - int graphiteTime, - int uraniumTime, - float heat - ) {} - - public void applyState(ReactorState state, ReactorBluePrintMenu c) { - c.countUraniumRod = state.countUraniumRod(); - c.countGraphiteRod = state.countGraphiteRod(); - c.graphiteTime = state.graphiteTime(); - c.uraniumTime = state.uraniumTime(); - c.heat = state.heat(); - c.sendUpdate = true; - } - -} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItemScreen.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItemScreen.java index 47e4960..0ad678c 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItemScreen.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintItemScreen.java @@ -52,23 +52,5 @@ protected void containerTick() { if (!ItemStack.matches(menu.player.getMainHandItem(), menu.contentHolder)) { menu.player.closeContainer(); } - - float coef = 0.1F; - - CompoundTag tag = menu.contentHolder.getOrDefault(CNDataComponents.PATTERN, new CompoundTag()); - - sendValueUpdate(tag, coef, - tag.getInt("graphiteTime"), - tag.getInt("uraniumTime"), - tag.getInt("countUraniumRod"), - tag.getInt("countGraphiteRod")+3 - ); - - - } - - - private static void sendValueUpdate(CompoundTag tag, float heat, int graphiteTime, int uraniumTime, int countGraphiteRod, int countUraniumRod) { - CatnipServices.NETWORK.sendToServer(new ReactorBluePrintItemPacket(tag, heat, graphiteTime, uraniumTime, countGraphiteRod, countGraphiteRod)); } } \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintMenu.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintMenu.java index 810981a..d07f1f3 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintMenu.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintMenu.java @@ -8,26 +8,35 @@ import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.neoforge.items.ItemStackHandler; import net.neoforged.neoforge.items.SlotItemHandler; import net.nuclearteam.createnuclear.*; -import net.nuclearteam.createnuclear.CNTags.CNItemTags; -import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType.TypeRodPredicate; import static net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintItem.getItemStorage; public class ReactorBluePrintMenu extends GhostItemMenu { - public float heat = 0F; - public int graphiteTime = 5000; - public int uraniumTime = 3600; - public int countGraphiteRod = 0; - public int countUraniumRod = 0; - public double progress = 0; - - public boolean sendUpdate = false; + /** + * Grid position of each of the 57 pattern slots, index-matched to {@link PatternData#slot()} + * and to {@code DefaultHeatCalculator#FORMATTED_PATTERN}: the reactor's proximity-heat + * calculation resolves neighbours by this exact index, so the array must never be reordered + * or resized independently of that grid. + */ + private static final int[][] POSITIONS = { + {3, 0}, {4, 0}, {5, 0}, + {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, + {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, + {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {8, 3}, + {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}, {8, 4}, + {0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {8, 5}, + {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6}, + {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}, + {3, 8}, {4, 8}, {5, 8} + }; private ReactorBluePrintData reactorBluePrintData; @@ -43,6 +52,10 @@ public static ReactorBluePrintMenu create(int id, Inventory inv, ItemStack stack return new ReactorBluePrintMenu(CNMenus.REACTOR_BLUEPRINT_MENU.get(), id, inv, stack); } + public ReactorBluePrintData getReactorBluePrintData() { + return reactorBluePrintData; + } + @Override protected boolean allowRepeats() { return false; @@ -51,35 +64,26 @@ protected boolean allowRepeats() { @Override protected void initAndReadInventory(ItemStack contentHolder) { super.initAndReadInventory(contentHolder); - int[][] positions = { - {3, 0}, {4, 0}, {5, 0}, - {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, - {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, - {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {8, 3}, - {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}, {8, 4}, - {0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {8, 5}, - {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6}, - {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}, - {3, 8}, {4, 8}, {5, 8} - }; - - - PatternData[] patternData = new PatternData[positions.length]; - ItemStack defaultStack = new ItemStack(Items.GLASS_PANE); - - for (int i = 0; i < positions.length; i++) { - patternData[i] = new PatternData(i, defaultStack); - } - - ReactorBluePrintData defaultPattern = new ReactorBluePrintData(0, 0, CNConfigs.common().rods.graphiteRodLifetime.get(), CNConfigs.common().rods.uraniumRodLifetime.get(), patternData, patternData); - reactorBluePrintData = contentHolder.getOrDefault(CNDataComponents.REACTOR_BLUE_PRINT_DATA, defaultPattern); + ItemStack glassPane = new ItemStack(Items.GLASS_PANE); + PatternData[] emptyPattern = new PatternData[POSITIONS.length]; + for (int i = 0; i < emptyPattern.length; i++) { + emptyPattern[i] = new PatternData(i, glassPane); + } - for (int i = 0; i < positions.length; i++) { - ItemStack stack = reactorBluePrintData.pattern()[i].stack().is(CNItemTags.COOLER.tag) || reactorBluePrintData.pattern()[i].stack().is(CNItemTags.FUEL.tag) - ? reactorBluePrintData.pattern()[i].stack() - : ItemStack.EMPTY; - ghostInventory.setStackInSlot(i, stack); + ReactorBluePrintData defaultData = new ReactorBluePrintData(0, 0, emptyPattern); + reactorBluePrintData = contentHolder.getOrDefault(CNDataComponents.REACTOR_BLUE_PRINT_DATA, defaultData); + + // Classified via RodType, not via the CNItemTags.COOLER/FUEL item tags: a rod can be + // registered as fuel/cooler through RodType.Builder without also carrying the matching + // item tag (e.g. the thorium rod), which made saved rods vanish on reopen when this used + // to filter on the tags instead. + Level level = playerInventory.player.level(); + PatternData[] pattern = reactorBluePrintData.pattern(); + for (int i = 0; i < POSITIONS.length; i++) { + ItemStack stack = pattern[i].stack(); + boolean isRod = TypeRodPredicate.isFuel(stack, level) || TypeRodPredicate.isCooled(stack, level); + ghostInventory.setStackInSlot(i, isRod ? stack : ItemStack.EMPTY); } } @@ -101,77 +105,48 @@ protected void addSlots() { } private void addPatternSlots() { - int startWidth = 8+23; + int startWidth = 8 + 23; int startHeight = 45; int incr = 18; - int i = 0; - int[][] positions = { - {3, 0}, {4, 0}, {5, 0}, - {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, - {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, - {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {8, 3}, - {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}, {8, 4}, - {0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {8, 5}, - {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6}, - {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}, - {3, 8}, {4, 8}, {5, 8} - }; - - for (int[] pos : positions) {// up and down not middle - this.addSlot(new SlotItemHandler(ghostInventory,i, startWidth + incr * pos[0], startHeight + incr * pos[1])); - i++; + + for (int i = 0; i < POSITIONS.length; i++) { + int[] pos = POSITIONS[i]; + this.addSlot(new SlotItemHandler(ghostInventory, i, startWidth + incr * pos[0], startHeight + incr * pos[1])); } } @Override protected void saveData(ItemStack contentHolder) { - int[][] positions = { - {3, 0}, {4, 0}, {5, 0}, - {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, - {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, - {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {8, 3}, - {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}, {8, 4}, - {0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {8, 5}, - {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6}, - {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}, - {3, 8}, {4, 8}, {5, 8} - }; - - PatternData[] patternData = new PatternData[positions.length]; + Level level = playerInventory.player.level(); + + // `pattern` keeps the grid exactly as the player laid it out. The normalized + // `patternAll` view (empty slots and non-rod items replaced by glass panes) is + // no longer built or stored here: ReactorBluePrintData#patternAll(Level) derives + // it from `pattern` on every call instead. See PatternReader. + PatternData[] pattern = new PatternData[POSITIONS.length]; + ItemStack glassPane = new ItemStack(Items.GLASS_PANE); int countGraphiteRod = 0; int countUraniumRod = 0; - for (int i = 0; i < positions.length; i++) { + for (int i = 0; i < POSITIONS.length; i++) { ItemStack stack = ghostInventory.getStackInSlot(i); - if (!stack.isEmpty() && stack.getCount() >= 1 && stack.getCount() <= 99) { - if (stack.is(CNItemTags.COOLER.tag)) { - countGraphiteRod++; - } - if (stack.is(CNItemTags.FUEL.tag)) { - countUraniumRod++; - } - patternData[i] = new PatternData(i, stack); - } else { - patternData[i] = new PatternData(i, new ItemStack(Items.GLASS_PANE)); + if (stack.isEmpty() || stack.getCount() < 1 || stack.getCount() > 99) { + pattern[i] = new PatternData(i, glassPane); + continue; } - } - - /*CreateNuclear.LOGGER.warn("PatternData slots:\n{}\n\n Count: {}", - Arrays.stream(patternData) - .map(pd -> "Slot " + pd.slot() + " => " + pd.stack()) - .collect(Collectors.joining("\n")), countGraphiteRod - );*/ - ReactorBluePrintData reactorBluePrintData = new ReactorBluePrintData(countGraphiteRod, countUraniumRod, CNConfigs.common().rods.graphiteRodLifetime.get(), CNConfigs.common().rods.uraniumRodLifetime.get(), patternData, patternData); - contentHolder.set(CNDataComponents.REACTOR_BLUE_PRINT_DATA, reactorBluePrintData); + boolean isFuel = TypeRodPredicate.isFuel(stack, level); + boolean isCooler = TypeRodPredicate.isCooled(stack, level); - ReactorBluePrintData newData = new ReactorBluePrintData(countGraphiteRod, countUraniumRod, CNConfigs.common().rods.graphiteRodLifetime.get(), CNConfigs.common().rods.uraniumRodLifetime.get(), patternData, patternData); + if (isCooler) countGraphiteRod++; + if (isFuel) countUraniumRod++; - if (!newData.equals(reactorBluePrintData)) { - contentHolder.set(CNDataComponents.REACTOR_BLUE_PRINT_DATA, newData); + pattern[i] = new PatternData(i, stack); } + ReactorBluePrintData data = new ReactorBluePrintData(countGraphiteRod, countUraniumRod, pattern); + contentHolder.set(CNDataComponents.REACTOR_BLUE_PRINT_DATA, data); } protected int getPlayerInventoryXOffset() { @@ -190,7 +165,7 @@ public boolean stillValid(Player player) { @Override public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { if (clickTypeIn == ClickType.THROW) { - if ( slotId >= 0 && slotId < 9) { + if (slotId >= 0 && slotId < 9) { clickTypeIn = ClickType.PICKUP; super.clicked(slotId, dragType, clickTypeIn, player); } @@ -198,4 +173,4 @@ public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player play } super.clicked(slotId, dragType, clickTypeIn, player); } -} \ No newline at end of file +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/test.txt b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/test.txt deleted file mode 100644 index e32c721..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/test.txt +++ /dev/null @@ -1,16 +0,0 @@ -contentHolder: - ReactorBluePrintData[ - countGraphiteRod=0, - countUraniumRod=0, - graphiteTime=0, - uraniumTime=0, - pattern=[Lnet.nuclearteam.createnuclear.content.multiblock.bluePrintItem.PatternData;@341d34dd, - patternAll=[Lnet.nuclearteam.createnuclear.content.multiblock.bluePrintItem.PatternData;@341d34dd], - [ - PatternData[slot=0, stack=1 minecraft:glass_pane], PatternData[slot=1, stack=1 minecraft:glass_pane], PatternData[slot=2, stack=1 minecraft:glass_pane], - PatternData[slot=3, stack=1 minecraft:glass_pane], PatternData[slot=4, stack=1 minecraft:glass_pane], PatternData[slot=5, stack=1 minecraft:glass_pane], - PatternData[slot=6, stack=1 minecraft:glass_pane], PatternData[slot=7, stack=1 minecraft:glass_pane], PatternData[slot=8, stack=1 minecraft:glass_pane], - PatternData[slot=9, stack=1 minecraft:glass_pane], PatternData[slot=10, stack=1 minecraft:glass_pane], PatternData[slot=11, stack=1 minecraft:glass_pane], - PatternData[slot=12, stack=1 minecraft:glass_pane], PatternData[slot=13, stack=1 minecraft:glass_pane], PatternData[slot=14, stack=1 minecraft:glass_pane], - PatternData[slot=15, stack=1 minecraft:glass_pane], PatternData[slot=16, stack=1 minecraft:glass_pane], PatternData[slot=17, stack=1 minecraft:glass_pane], PatternData[slot=18, stack=1 minecraft:glass_pane], PatternData[slot=19, stack=1 minecraft:glass_pane], PatternData[slot=20, stack=1 minecraft:glass_pane], PatternData[slot=21, stack=1 minecraft:glass_pane], PatternData[slot=22, stack=1 minecraft:glass_pane], PatternData[slot=23, stack=1 minecraft:glass_pane], PatternData[slot=24, stack=1 minecraft:glass_pane], PatternData[slot=25, stack=1 minecraft:glass_pane], PatternData[slot=26, stack=1 minecraft:glass_pane], PatternData[slot=27, stack=1 minecraft:glass_pane], PatternData[slot=28, stack=1 minecraft:glass_pane], PatternData[slot=29, stack=1 minecraft:glass_pane], PatternData[slot=30, stack=1 minecraft:glass_pane], PatternData[slot=31, stack=1 minecraft:glass_pane], PatternData[slot=32, stack=1 minecraft:glass_pane], PatternData[slot=33, stack=1 minecraft:glass_pane], PatternData[slot=34, stack=1 minecraft:glass_pane], PatternData[slot=35, stack=1 minecraft:glass_pane], PatternData[slot=36, stack=1 minecraft:glass_pane], PatternData[slot=37, stack=1 minecraft:glass_pane], PatternData[slot=38, stack=1 minecraft:glass_pane], PatternData[slot=39, stack=1 minecraft:glass_pane], PatternData[slot=40, stack=1 minecraft:glass_pane], PatternData[slot=41, stack=1 minecraft:glass_pane], PatternData[slot=42, stack=1 minecraft:glass_pane], PatternData[slot=43, stack=1 minecraft:glass_pane], PatternData[slot=44, stack=1 minecraft:glass_pane], PatternData[slot=45, stack=1 minecraft:glass_pane], PatternData[slot=46, stack=1 minecraft:glass_pane], PatternData[slot=47, stack=1 minecraft:glass_pane], PatternData[slot=48, stack=1 minecraft:glass_pane], PatternData[slot=49, stack=1 minecraft:glass_pane], PatternData[slot=50, stack=1 minecraft:glass_pane], PatternData[slot=51, stack=1 minecraft:glass_pane], PatternData[slot=52, stack=1 minecraft:glass_pane], PatternData[slot=53, stack=1 minecraft:glass_pane], -PatternData[slot=54, stack=1 minecraft:glass_pane], PatternData[slot=55, stack=1 minecraft:glass_pane], PatternData[slot=56, stack=1 minecraft:glass_pane]] \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/casing/ReactorCasing.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/casing/ReactorCasing.java index cbdee86..57331ed 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/casing/ReactorCasing.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/casing/ReactorCasing.java @@ -4,36 +4,35 @@ import com.simibubi.create.foundation.block.IBE; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; import net.minecraft.network.chat.Component; import net.minecraft.util.StringRepresentable; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.nuclearteam.createnuclear.CNBlockEntityTypes; import net.nuclearteam.createnuclear.CNBlocks; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; -import net.nuclearteam.createnuclear.content.multiblock.input.ReactorInput; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.content.multiblock.input.item.ReactorRodInput; +import net.nuclearteam.createnuclear.content.multiblock.pattern.ReactorPattern; import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.List; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @SuppressWarnings({"deprecation", "unused"}) public class ReactorCasing extends Block implements IWrenchable, IBE { private final TypeBlock typeBlock; + protected ReactorPattern pattern = new ReactorPattern(); public ReactorCasing(Properties properties, TypeBlock tBlock) { super(properties); @@ -44,22 +43,20 @@ public ReactorCasing(Properties properties, TypeBlock tBlock) { @Override // Called when the block is placed on the world public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { super.onPlace(state, level, pos, oldState, movedByPiston); - List players = level.players(); - FindController(pos, level, players, true); + // change nearby chunks' biomes to the mod biome (radius in blocks) + pattern.findController(pos, level, true); } - @Override // called when the player destroys the block, with or without a tool - public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { - super.playerDestroy(level, player, pos, state, blockEntity, tool); - List players = level.players(); - FindController(pos, level, players, false); + @Override + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity pPlacer, ItemStack stack) { + super.setPlacedBy(level, pos, state, pPlacer, stack); + MultiblockHelpers.handleAdvancedPlacedBy(pos, level, pPlacer); } @Override public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { super.onRemove(state, level, pos, newState, movedByPiston); - List players = level.players(); - FindController(pos, level, players, false); + pattern.findController(pos, level, false); } @Override @@ -69,34 +66,12 @@ public InteractionResult onWrenched(BlockState state, UseOnContext context) { Player player = context.getPlayer(); if (player.getItemInHand(InteractionHand.OFF_HAND).is(Blocks.HOPPER.asItem())) { - level.setBlock(pos, CNBlocks.REACTOR_INPUT.getDefaultState().setValue(ReactorInput.FACING, context.getClickedFace()), 2); + level.setBlock(pos, CNBlocks.REACTOR_ROD_INPUT.getDefaultState().setValue(ReactorRodInput.FACING, context.getClickedFace()), 2); player.sendSystemMessage(Component.translatable("reactor.update.casing.input")); } return InteractionResult.SUCCESS; } - // En attendant le controller pour verifier le pattern - public ReactorControllerBlock FindController(BlockPos blockPos, Level level, List players, boolean first){ // Function that checks the surrounding blocks in order - BlockPos newBlock; // to find the controller and verify the pattern - Vec3i pos = new Vec3i(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - for (int y = pos.getY()-3; y != pos.getY()+4; y+=1) { - for (int x = pos.getX()-5; x != pos.getX()+5; x+=1) { - for (int z = pos.getZ()-5; z != pos.getZ()+5; z+=1) { - newBlock = new BlockPos(x, y, z); - if (level.getBlockState(newBlock).is(CNBlocks.REACTOR_CONTROLLER.get())) { // verifying the pattern - ReactorControllerBlock controller = (ReactorControllerBlock) level.getBlockState(newBlock).getBlock(); - controller.Verify(level.getBlockState(newBlock), newBlock, level, players, first); - ReactorControllerBlockEntity entity = controller.getBlockEntity(level, newBlock); - if (entity.created) { - return controller; - } - } - } - } - } - return null; - } - @Override public Class getBlockEntityClass() { return ReactorCasingEntity.class; diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/EventTriggerPacket.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/EventTriggerPacket.java deleted file mode 100644 index cec36b6..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/EventTriggerPacket.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.nuclearteam.createnuclear.content.multiblock.controller; - -import net.createmod.catnip.net.base.ClientboundPacketPayload; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.api.distmarker.OnlyIn; -import net.nuclearteam.createnuclear.CNPackets; -import net.nuclearteam.createnuclear.foundation.events.overlay.EventTextOverlay; - -/** - * Packet sent from server to client to trigger a localized event overlay. - */ -public record EventTriggerPacket(int duration) implements ClientboundPacketPayload { - public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.INT, EventTriggerPacket::duration, - EventTriggerPacket::new - ); - - @Override - public PacketTypeProvider getTypeProvider() { - return CNPackets.TRIGGER_EVENT_TEXT_OVERLAY; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void handle(LocalPlayer player) { - EventTextOverlay.triggerEvent(duration); - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlock.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlock.java index d4f4e9d..b7c13e7 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlock.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlock.java @@ -6,12 +6,16 @@ import net.minecraft.ChatFormatting; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -22,28 +26,44 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.phys.BlockHitResult; import net.nuclearteam.createnuclear.*; -import net.nuclearteam.createnuclear.content.multiblock.CNMultiblock; -import net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutput; -import net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutputEntity; +import net.nuclearteam.createnuclear.content.multiblock.IHeat; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.content.multiblock.ReactorAssembler; +import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintData; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.PersistentFluidLocks; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancement; import net.nuclearteam.createnuclear.foundation.block.HorizontalDirectionalReactorBlock; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; +import net.nuclearteam.createnuclear.foundation.utility.NotifyUtil; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.List; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault @SuppressWarnings("deprecation") public class ReactorControllerBlock extends HorizontalDirectionalReactorBlock implements IWrenchable, IBE { public static final BooleanProperty ASSEMBLED = BooleanProperty.create("assembled"); + /** + * Whether the reactor is currently producing energy. Recomputed server-side on + * every tick by the controller block entity and synced to the client by vanilla, + * which is what drives the running-sound loop and the lit controller texture. + */ + public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); public ReactorControllerBlock(Properties properties) { super(properties); + this.registerDefaultState(this.stateDefinition.any() + .setValue(FACING, Direction.NORTH) + .setValue(ASSEMBLED, false) + .setValue(ACTIVE, false) // Inactive by default + ); } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(FACING).add(ASSEMBLED); + builder.add(FACING).add(ASSEMBLED).add(ACTIVE); super.createBlockStateDefinition(builder); } @@ -51,12 +71,22 @@ protected void createBlockStateDefinition(StateDefinition.Builder be.created = false); + if (worldIn.isClientSide) + return; + // A direct neighbor of the controller has changed. Do NOT blindly disassemble: + // only do so if the structure is actually broken. Otherwise, placing/replacing a + // block adjacent to the controller (frame above/below, input/alarm on the sides, + // cooler behind) would invalidate the assembly that was just validated. + // disassemble() checks findStructure and does nothing if the structure is complete. + if (state.getValue(ASSEMBLED)) + ReactorAssembler.disassemble(pos, worldIn); } @Override @@ -68,35 +98,50 @@ protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Lev if (!(blockEntity instanceof ReactorControllerBlockEntity controllerBlockEntity)) return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; ItemStack heldItem = player.getItemInHand(hand); + if (heldItem.is(Items.DEBUG_STICK)) { + withBlockEntityDo(level, pos, be -> be.logReactorConnections(player)); + } if (!state.getValue(ASSEMBLED)) { - player.sendSystemMessage(Component.translatable("reactor.info.assembled.none").withStyle(ChatFormatting.RED)); } else { - if (heldItem.is(CNItems.REACTOR_BLUEPRINT.get()) && controllerBlockEntity.inventory.getItem(0).isEmpty()){ + if (heldItem.is(CNItems.REACTOR_BLUEPRINT.get()) && controllerBlockEntity.getInventoryObject().getItem(0).isEmpty() + && heldItem.getOrDefault(CNDataComponents.REACTOR_BLUE_PRINT_DATA, ReactorBluePrintData.EMPTY) != ReactorBluePrintData.EMPTY){ withBlockEntityDo(level, pos, be -> { - be.inventory.setStackInSlot(0, heldItem); - be.configuredPattern = heldItem; + be.getInventoryObject().setStackInSlot(0, heldItem); + be.setConfiguredPattern(heldItem); player.setItemInHand(hand, ItemStack.EMPTY); }); + // Inserting the blueprint is what starts energy production: this is the activation + // cue, not the multiblock assembly one (that lives in ReactorAssembler). + // One-shot played server-side (null player) so it broadcasts to nearby clients. + level.playSound(null, pos, CNSoundEvents.REACTOR_ACTIVATION.getMainEvent(), SoundSource.BLOCKS, 1.0f, 1.0f); return ItemInteractionResult.SUCCESS; } - else if (heldItem.isEmpty() && !controllerBlockEntity.inventory.getItem(0).isEmpty()) { + else if (heldItem.isEmpty() && !controllerBlockEntity.getInventoryObject().getItem(0).isEmpty()) { withBlockEntityDo(level, pos, be -> { - player.setItemInHand(hand, be.inventory.getItem(0)); - be.inventory.setStackInSlot(0, ItemStack.EMPTY); - be.configuredPattern = ItemStack.EMPTY; - be.total = 0.0; - be.rotate(be.getBlockState(), new BlockPos(be.getBlockPos().getX(), be.getBlockPos().getY() + (-3), be.getBlockPos().getZ()), be.getLevel(), 0, false); + ItemStack blueprint = be.getInventoryObject().getItem(0); + int storedHeat = Math.round(blueprint.getOrDefault(CNDataComponents.HEAT, 0f)); + if (IHeat.HeatLevel.of(storedHeat, be.getMultiblockSize()) == IHeat.HeatLevel.DANGER) { + be.getAdvancement().setPlayer(player.getUUID()); + be.getAdvancement().awardPlayer(CNAdvancement.NO_TIME_TO_DIE); + } + player.setItemInHand(hand, blueprint); + be.getInventoryObject().setStackInSlot(0, ItemStack.EMPTY); + be.setConfiguredPattern(ItemStack.EMPTY); + //be.clearTimers(); // uncomment if the timer should reset when the reactor stops + be.getOutputManager().rotateOutputs(be.getLevel(), be.getAssembled(), 0); be.notifyUpdate(); }); + // Blueprint removed: the multiblock stays assembled, it just stops producing. + level.playSound(null, pos, CNSoundEvents.REACTOR_SHUT_OFF.getMainEvent(), SoundSource.BLOCKS, 1.0f, 1.0f); state.setValue(ASSEMBLED, false); return ItemInteractionResult.SUCCESS; } - else if (!heldItem.isEmpty() && !controllerBlockEntity.inventory.getItem(0).isEmpty()) { + else if (!heldItem.isEmpty() && !controllerBlockEntity.getInventoryObject().getItem(0).isEmpty()) { return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; } } @@ -108,90 +153,42 @@ public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState n if (!state.hasBlockEntity() || state.getBlock() == newState.getBlock()) return; - withBlockEntityDo(worldIn, pos, be -> ItemHelper.dropContents(worldIn, pos, be.inventory)); + withBlockEntityDo(worldIn, pos, be -> ItemHelper.dropContents(worldIn, pos, be.getInventoryObject())); worldIn.removeBlockEntity(pos); - ReactorControllerBlock controller = (ReactorControllerBlock) state.getBlock(); - - controller.Rotate(state, pos.below(3), worldIn, 0); - List players = worldIn.players(); - for (Player p : players) { - p.sendSystemMessage(Component.translatable("reactor.info.assembled.destroyer")); + if (worldIn instanceof ServerLevel serverLevel) { + PersistentFluidLocks.get(serverLevel).clearLock(pos); } + + if (!state.getValue(ASSEMBLED)) + return; + + int configRadius = CNConfigs.server().notify.warningDistance.get(); + boolean configWarnAll = CNConfigs.server().notify.warnAllPlayers.get(); + NotifyUtil.sendActionBar(worldIn, pos, + CreateNuclearLang.translate("notification.reactor.disassembled"), + ChatFormatting.GOLD, configRadius, configWarnAll + ); } @Override - public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { - super.onPlace(state, level, pos, oldState, movedByPiston); + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity pPlacer, ItemStack stack) { + super.setPlacedBy(level, pos, state, pPlacer, stack); + MultiblockHelpers.handleAdvancedPlacedBy(pos, level, pPlacer); if (state.getValue(ASSEMBLED)) return; - List players = level.players(); - ReactorControllerBlock controller = (ReactorControllerBlock) state.getBlock(); - controller.Verify(state, pos, level, players, true); + ReactorAssembler.assemble(pos, level); } @Override public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { super.playerDestroy(level, player, pos, state, blockEntity, tool); - ReactorControllerBlock controller = (ReactorControllerBlock) state.getBlock(); - ReactorControllerBlockEntity entity = controller.getBlockEntity(level, pos); - if (!entity.created) - return; - controller.Rotate(state, pos.below(3), level, 0); - List players = level.players(); - for (Player p : players) { + if (!(blockEntity instanceof ReactorControllerBlockEntity entity)) return; + if (!entity.isAssembled()) return; + for (Player p : level.players()) { p.sendSystemMessage(Component.translatable("reactor.info.assembled.creator")); } - } - - // this is the Function that verifies if the pattern is correct (as a test, we added the energy output) - public void Verify(BlockState state, BlockPos pos, Level level, List players, boolean create){ - ReactorControllerBlock controller = (ReactorControllerBlock) level.getBlockState(pos).getBlock(); - ReactorControllerBlockEntity entity = controller.getBlockEntity(level, pos); - var result = CNMultiblock.REGISTRATE_MULTIBLOCK.findStructure(level, pos); // control the pattern - if (result != null) { // the pattern is correct - - for (Player player : players) { - if (create && !entity.created) { - player.sendSystemMessage(Component.translatable("reactor.info.assembled.creator")); - level.setBlockAndUpdate(pos, state.setValue(ASSEMBLED, true)); - entity.created = true; - entity.destroyed = false; - } - } - return; - } - - // the pattern is incorrect - for (Player player : players) { - if (!create && !entity.destroyed) - { - player.sendSystemMessage(Component.translatable("reactor.info.assembled.destroyer")); - level.setBlockAndUpdate(pos, state.setValue(ASSEMBLED, false)); - entity.created = false; - entity.destroyed = true; - Rotate(state, pos.below(3), level, 0); - } - } - } - public void Rotate(BlockState state, BlockPos pos, Level level, int rotation) { - if (level.getBlockState(pos).is(CNBlocks.REACTOR_OUTPUT.get())) { - ReactorOutput block = (ReactorOutput) level.getBlockState(pos).getBlock(); - ReactorOutputEntity entity = block.getBlockEntityType().getBlockEntity(level, pos); - - if (state.getValue(ASSEMBLED) && rotation != 0) { // Starting the energy - entity.speed = rotation; - entity.setSpeed(Math.abs(entity.speed)); - } else { // stopping the energy - - entity.setSpeed(0); - entity.speed = 0; - } - entity.updateSpeed = true; - entity.updateGeneratedRotation(); - - entity.setSpeed(rotation); - } +// entity.removeIOAll(); } @Override @@ -203,5 +200,4 @@ public Class getBlockEntityClass() { public BlockEntityType getBlockEntityType() { return CNBlockEntityTypes.REACTOR_CONTROLLER.get(); } - } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlockEntity.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlockEntity.java index 021e4a1..1c18393 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlockEntity.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlockEntity.java @@ -1,450 +1,580 @@ package net.nuclearteam.createnuclear.content.multiblock.controller; -import com.simibubi.create.AllDataComponents; import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.IInteractionChecker; +import net.minecraft.client.Minecraft; +import net.minecraft.core.*; import lib.multiblock.SimpleMultiBlockAislePatternBuilder; -import net.createmod.catnip.data.Iterate; import net.createmod.catnip.platform.CatnipServices; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.HolderLookup; +import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Explosion; +import net.minecraft.world.item.component.CustomData; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import net.neoforged.neoforge.capabilities.Capabilities; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.material.Fluid; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.IItemHandler; -import net.neoforged.neoforge.items.wrapper.EmptyItemHandler; -import net.nuclearteam.createnuclear.*; -import net.nuclearteam.createnuclear.content.multiblock.IHeat; -import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.PatternData; + +import net.nuclearteam.createnuclear.CNDataComponents; +import net.nuclearteam.createnuclear.CNSoundEvents; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.multiblock.IMultiblockController; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintData; -import net.nuclearteam.createnuclear.content.multiblock.input.ReactorInputEntity; -import net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutput; -import net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutputEntity; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorGoggleTooltipRenderer; +import net.nuclearteam.createnuclear.content.multiblock.controller.service.*; +import net.nuclearteam.createnuclear.content.multiblock.controller.snapshot.ReactorInputSnapshot; +import net.nuclearteam.createnuclear.content.multiblock.controller.snapshot.ReactorInputSnapshotBuilder; +import net.nuclearteam.createnuclear.content.multiblock.IHeat; +import net.nuclearteam.createnuclear.content.multiblock.reactorLogic.HeatBalance; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancement; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancementBehaviour; +import net.nuclearteam.createnuclear.content.multiblock.controller.consumable.ConsumptionCycleManager; -import java.util.LinkedHashSet; +import java.util.ArrayList; import java.util.List; -import static net.nuclearteam.createnuclear.content.multiblock.CNMultiblock.*; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.PersistentFluidLocks; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.*; +import net.nuclearteam.createnuclear.content.multiblock.pattern.ReactorPattern; +import net.nuclearteam.createnuclear.content.multiblock.reactorLogic.HeatManager; + import static net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock.ASSEMBLED; -@SuppressWarnings({"unused"}) -public class ReactorControllerBlockEntity extends SmartBlockEntity implements IInteractionChecker, IHaveGoggleInformation { - public boolean destroyed = false; - public boolean created = false; - public boolean test = true; - public int speed = 16; // This is the result speed of the reactor, change this to change the total capacity - - public boolean sendUpdate; - - public ReactorControllerBlock controller; - - public ReactorControllerInventory inventory; - - - //private boolean powered; - public State powered = State.OFF; - public float reactorPower; - public float lastReactorPower; - int overFlowHeatTimer = 0; - int overFlowLimiter = 30; - double overHeat = 0; - public int baseUraniumHeat = 25; - public int baseGraphiteHeat = -10; - public int proximityUraniumHeat = 5; - public int proximityGraphiteHeat = -5; - public int maxUraniumPerGraphite = 3; - public int graphiteTimer = 3600; - public int uraniumTimer = 3600; - public int tmpGraphiteTimer = graphiteTimer; - public int tmpUraniumTimer = uraniumTimer; - public int countUraniumRod; - public int countGraphiteRod; - public int heat; - public double total; - private boolean isTotal = false; - public CompoundTag screen_pattern = new CompoundTag(); - public ItemStack configuredPattern; - - private ItemStack fuelItem; - private ItemStack coolerItem; - - private final int[][] formattedPattern = new int[][]{ - {99,99,99,0,1,2,99,99,99}, - {99,99,3,4,5,6,7,99,99}, - {99,8,9,10,11,12,13,14,99}, - {15,16,17,18,19,20,21,22,23}, - {24,25,26,27,28,29,30,31,32}, - {33,34,35,36,37,38,39,40,41}, - {99,42,43,44,45,46,47,48,99}, - {99,99,49,50,51,52,53,99,99}, - {99,99,99,54,55,56,99,99,99} - }; - private final int[][] offsets = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} }; +@SuppressWarnings({ "unused" }) +public class ReactorControllerBlockEntity extends SmartBlockEntity + implements IInteractionChecker, IHaveGoggleInformation, IMultiblockController { + /** + * The assembled state is stored in the block state + * (`ReactorControllerBlock.ASSEMBLED`). + * Use the helper accessors below to query or toggle it to keep + * entity/blockstate consistent. + */ + private final ReactorPattern pattern = new ReactorPattern(); + private final ReactorControllerInventory inventory; + private int countFuelRod; + private int countCoolerRod; + private HeatBalance heatBalance; + private int heat; + private int lastAppliedOutputHeat; + private boolean isExploding = false; + + /** Client-only looping "running" sound instance; never accessed server-side. */ + @OnlyIn(Dist.CLIENT) + private ReactorRunningSoundInstance runningSound; + + private final ConsumptionCycleManager cycleManager = new ConsumptionCycleManager(); + private double liquidLife; + private ItemStack configuredPattern; + + private List bigFluidStack; + + private int reactorSize = 0; + private Direction reactorFacing = null; + // les pos sont [xMin, xMax, yMin, yMax, zMin, zMax] + private BoundingBox reactorPos; + + + private boolean needsToResolveEntities = false; + private double fluidBuffer = 0.0; + + private CNAdvancementBehaviour advancement; + + private final ReactorInputManagerI inputManager; + private final ReactorOutputManagerI outputManager; + private final ReactorInputFluidManagerI inputFluidManager; + private final ReactorAlarmManagerI alarmManager; + private final ReactorFrameDisplayManagerI frameDisplayManager; + + private ReactorDisplayState displayState = ReactorDisplayState.EMPTY; + + // services (dependencies) - abstracted behind interfaces to follow DIP + private final IHeatService heatService; + private final IPersistenceService persistenceService; + private final IExplosionService meltdownExecutor; + private final IReactorHeatUpdateCoordinator heatCoordinator; + private final IFluidConsumptionRateCalculator fluidRateCalculator; + /** Counts down to the next explosion once in danger; keeps the original 1-tick lag against the heat recalculated later this tick. */ + private final IReactorMeltdownMonitor meltdownMonitor; + /** Drives the alarm blocks based on the danger flag; built in {@link #addBehaviours} since it depends on {@link #advancement}. */ + private IReactorAlarmCoordinator alarmCoordinator; + + // service fields are injected; implementations live in separate classes + + // --- Accessors used by external services (persistence) --- + public ReactorControllerInventory getInventoryObject() { + return this.inventory; + } + + public void deserializeInventory(HolderLookup.Provider registries, CompoundTag tag) { + this.inventory.deserializeNBT(registries, tag); + } + + public CompoundTag serializeInventory(HolderLookup.Provider registries) { + return this.inventory.serializeNBT(registries); + } + + public ItemStack getConfiguredPattern() { + return this.configuredPattern; + } + + public void setConfiguredPattern(ItemStack stack) { + this.configuredPattern = stack; + } + + /** + * Current heat stored on the blueprint stack. + *

+ * Replaces the Forge {@code getConfiguredPatternTag().getDouble("heat")}: the value now + * lives in the {@link CNDataComponents#HEAT} data component, because reading the stack's + * NBT tag back on NeoForge yields a defensive copy. + */ + public int getConfiguredPatternHeat() { + if (this.configuredPattern.isEmpty()) return 0; + return Math.round(this.configuredPattern.getOrDefault(CNDataComponents.HEAT, 0f)); + } + + public CompoundTag getConfiguredPatternTag() { + return this.configuredPattern.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); + } + + private ReactorBluePrintData getConfiguredPatternData() { + return getConfiguredPattern().getOrDefault(CNDataComponents.REACTOR_BLUE_PRINT_DATA, ReactorBluePrintData.EMPTY); + } + /** @return the first loaded fluid, or {@code null} if no fluid is present. */ + private BigFluidStack currentFluidStack() { + return bigFluidStack.isEmpty() ? null : bigFluidStack.get(0); + } + public List getBigFluidStack() { + return this.bigFluidStack; + } + public void setBigFluidStack(List b) { + this.bigFluidStack = b; + } + + public int getMultiblockSize() { + return this.reactorSize; + } + + public void setMultiblockSize(int s) { + this.reactorSize = s; + } + + @Override + public Direction getMultiblockFacing() { + return this.reactorFacing; + } + + @Override + public void setMultiblockFacing(Direction f) { + this.reactorFacing = f; + } + + public CNAdvancementBehaviour getAdvancement() { + return this.advancement; + } + + /** Main constructor allowing dependency injection for testability and DIP compliance. */ + public BoundingBox getMultiblockPos() { + return this.reactorPos; + } + + public void setMultiblockStructure(BoundingBox p) { + this.reactorPos = p; + } + + public void clearTimers() { + this.cycleManager.clear(); + } + + public ReactorFrameDisplayManagerI getFrameDisplayManager() { + return this.frameDisplayManager; + } + + public ReactorInputFluidManagerI getInputFluidManager() { + return this.inputFluidManager; + } + + public ReactorOutputManagerI getOutputManager() { + return this.outputManager; + } + + public void setDisplayState(ReactorDisplayState state) { + this.displayState = state; + } + + public ReactorDisplayState getDisplayState() { + return this.displayState; + } + + private List allManagers() { + return List.of(inputManager, inputFluidManager, outputManager, alarmManager); + } + + /** + * Main constructor allowing dependency injection for testability and DIP + * compliance. + */ public ReactorControllerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); - inventory = new ReactorControllerInventory(this); - configuredPattern = ItemStack.EMPTY; + this.inventory = new ReactorControllerInventory(this); + this.configuredPattern = ItemStack.EMPTY; + this.heatBalance = new HeatBalance(0, 0); + + this.inputManager = new ReactorInputManager(); + this.outputManager = new ReactorOutputManager(); + this.inputFluidManager = new ReactorInputFluidManager(); + this.alarmManager = new ReactorAlarmManager(); + this.frameDisplayManager = new ReactorFrameDisplayManager(); + + this.bigFluidStack = new ArrayList<>(); + + this.heatService = new DefaultHeatService(new HeatManager()); + this.persistenceService = new DefaultPersistenceService(); + this.meltdownExecutor = new ReactorMeltdownExecutor(); + this.heatCoordinator = new ReactorHeatUpdateCoordinator(this.heatService); + this.fluidRateCalculator = new FluidConsumptionRateCalculator(this.heatService); + this.meltdownMonitor = new ReactorMeltdownMonitor(); } @Override public void addBehaviours(List behaviours) { - + behaviours.add(advancement = new CNAdvancementBehaviour(this, CNAdvancement.T1_REACTOR, CNAdvancement.T2_REACTOR, CNAdvancement.T3_REACTOR, CNAdvancement.NO_TIME_TO_DIE, CNAdvancement.SILENCE_THE_CORE)); + this.alarmCoordinator = new ReactorAlarmCoordinator(advancement); } - public boolean getAssembled() { // permet de savoir si le réacteur est formé ou pas. + public boolean getAssembled() { // returns whether the reactor structure is currently assembled BlockState state = getBlockState(); return state.getValue(ASSEMBLED); } @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - if(!configuredPattern.isEmpty()) { - CreateLang.translate("gui.gauge.info_header").style(ChatFormatting.GRAY).forGoggles(tooltip); - IHeat.HeatLevel.getName("reactor_controller").style(ChatFormatting.GRAY).forGoggles(tooltip); - - IHeat.HeatLevel.getFormattedHeatText(heat).forGoggles(tooltip); - - if (fuelItem.isEmpty()) { - // if rod empty we initialize it at 1 (and display it as 0) to avoid having air item displayed instead of the rod - IHeat.HeatLevel.getFormattedItemText(new ItemStack(CNItems.URANIUM_ROD.asItem(), 1), true).forGoggles(tooltip); - } else { - IHeat.HeatLevel.getFormattedItemText(fuelItem, false).forGoggles(tooltip); - } - - if (fuelItem.isEmpty()) { - // if rod empty we initialize it at 1 (and display it as 0) to avoid having air item displayed instead of the rod - IHeat.HeatLevel.getFormattedItemText(new ItemStack(CNItems.GRAPHITE_ROD.asItem(), 1), true).forGoggles(tooltip); - } else { - IHeat.HeatLevel.getFormattedItemText(coolerItem, false).forGoggles(tooltip); - } + if (getConfiguredPatternData() == ReactorBluePrintData.EMPTY) { + return false; } + ReactorGoggleTooltipRenderer.render(tooltip, displayState, getConfiguredPatternHeat(), isPlayerSneaking, reactorSize); + return true; } - //(Si les methode read et write ne sont pas implémenté alors lorsque l'on relance le monde minecraft les items dans le composant auront disparu !) + // (If read/write are not implemented, the items stored in this block entity's + // inventory will be lost when the world is reloaded!) @Override - protected void read(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) { //Permet de stocker les item 1/2 - if (!clientPacket) { - inventory.deserializeNBT(registries, tag.getCompound("inventory")); - } - configuredPattern = ItemStack.EMPTY; - if (tag.contains("configuredPattern")) { - ItemStack.parse(registries, tag.getCompound("configuredPattern")).ifPresent(i -> configuredPattern = i); + protected void read(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) { + super.read(compound, registries, clientPacket); // Always call first to restore the base coordinates + // delegate managers and persistence + this.inputManager.read(compound); + this.outputManager.read(compound); + this.inputFluidManager.read(compound); + this.alarmManager.read(compound); + this.frameDisplayManager.read(compound); + + this.persistenceService.readBasicState(this, compound, registries, clientPacket); + this.needsToResolveEntities = true; + + this.cycleManager.clear(); + if (compound.contains("cycleManager")) { + this.cycleManager.deserializeNBT(compound.getCompound("cycleManager")); } + } - coolerItem = ItemStack.EMPTY; - if (tag.contains("coolerItem")) { - ItemStack.parse(registries, tag.getCompound("coolerItem")).ifPresent(i -> coolerItem = i); - } + @Override + protected void write(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) { + super.write(compound, registries, clientPacket); + this.inputManager.write(compound); + this.outputManager.write(compound); + this.inputFluidManager.write(compound); + this.alarmManager.write(compound); + this.frameDisplayManager.write(compound); - fuelItem = ItemStack.EMPTY; - if (tag.contains("fuelItem")) { - ItemStack.parse(registries, tag.getCompound("fuelItem")).ifPresent(i -> fuelItem = i); - } + this.persistenceService.writeBasicState(this, compound, registries, clientPacket); - total = tag.getDouble("total"); - heat = tag.getInt("heat"); - super.read(tag, registries, clientPacket); + compound.put("cycleManager", cycleManager.serializeNBT()); } - @Override - protected void write(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) { //Permet de stocker les item 2/2 - if (!clientPacket) { - compound.put("inventory", inventory.serializeNBT(registries)); + public boolean isAssembled() { + if (level == null) + return false; + try { + return level.getBlockState(worldPosition).getValue(ASSEMBLED); + } catch (Exception e) { + return false; } + } - if (configuredPattern != null) compound.put("configuredPattern", configuredPattern.saveOptional(registries)); - if (coolerItem != null) compound.put("coolerItem", coolerItem.saveOptional(registries)); - if (fuelItem != null) compound.put("fuelItem", fuelItem.saveOptional(registries)); + public void setAssembled(boolean assembled) { + if (level == null) + return; + level.setBlockAndUpdate(worldPosition, getBlockState().setValue(ASSEMBLED, assembled)); + this.setChanged(); + } - compound.putDouble("total", Double.isNaN(total) ? total : calculateProgress()); - compound.putInt("heat", heat); - super.write(compound, registries, clientPacket); + public void logReactorConnections(Player player) { + ReactorDebugDiagnostics.sendReactorConnectionsTo(player, level, inputManager, inputFluidManager, outputManager, alarmManager); } - public enum State { - ON, OFF + private void updateReactorStateVisibility() { + if (level == null || level.isClientSide) return; + + BlockState state = getBlockState(); + if (!(state.getBlock() instanceof ReactorControllerBlock)) return; + + boolean currentActive = state.getValue(ReactorControllerBlock.ACTIVE); + + // The reactor is "ACTIVE" (ON) only if it is assembled AND has the resources required to run + boolean targetActive = isAssembled() && heatCoordinator.canRun(getConfiguredPattern(), getDisplayState(), getInputFluidManager(), level, getAssembled()); + + if (currentActive != targetActive) { + level.setBlock(worldPosition, state.setValue(ReactorControllerBlock.ACTIVE, targetActive), 3); + } } @Override public void tick() { super.tick(); - if (level.isClientSide) + if (level.isClientSide) { + tickRunningSound(); + return; + } + if (isExploding) return; + // Heat value written by the previous tick's handleAssembledState(); this tick's recalculated + // heat is not visible here yet, so the alarm/meltdown danger flag is intentionally 1 tick behind. + int currentHeat = getConfiguredPatternHeat(); + boolean isDanger = alarmCoordinator.computeDanger(currentHeat, this.getMultiblockSize()); - if (isEmptyConfiguredPattern()) { - ReactorBluePrintData data = getReactorBluePrintData(); - countGraphiteRod = data.countGraphiteRod(); - countUraniumRod = data.countUraniumRod(); + alarmCoordinator.update(level, alarmManager, isDanger); + + IReactorMeltdownMonitor.MeltdownState meltdownState = meltdownMonitor.tick(level, getBlockPos(), isDanger); + + if (meltdownState == IReactorMeltdownMonitor.MeltdownState.EXPLODE) { + if (level instanceof ServerLevel serverLevel) { + this.meltdownExecutor.triggerExplosion(serverLevel, getBlockPos(), reactorSize, countFuelRod); - if (!isTotal) { - total = calculateProgress(); - isTotal = true; - } - BlockEntity blockEntity = level.getBlockEntity(getBlockPosForReactor('I')); - - if (blockEntity instanceof ReactorInputEntity be) { - fuelItem = be.inventory.getStackInSlot(0); - coolerItem = be.inventory.getStackInSlot(1); - - IItemHandler capability = level.getCapability(Capabilities.ItemHandler.BLOCK, be.getBlockPos(), Direction.NORTH.getOpposite()); - if (capability == null) - capability = EmptyItemHandler.INSTANCE; - if (tmpUraniumTimer >= 0) { - tmpUraniumTimer -= 1 * countUraniumRod; - } else { - ItemStack extractItem1 = capability.extractItem(0, 1, false); - tmpUraniumTimer = uraniumTimer; - } - if (tmpGraphiteTimer >= 0) { - tmpGraphiteTimer -= 1 * countGraphiteRod; - } else { - ItemStack extractItem2 = capability.extractItem(1, 1, false); - tmpGraphiteTimer = graphiteTimer; - } - - if (!fuelItem.isEmpty() && !coolerItem.isEmpty()) { - heat = (int) calculateHeat(inventory.getItem(0)); - if (updateTimers()) { - - if (IHeat.HeatLevel.of(heat) == IHeat.HeatLevel.SAFETY || IHeat.HeatLevel.of(heat) == IHeat.HeatLevel.CAUTION || IHeat.HeatLevel.of(heat) == IHeat.HeatLevel.WARNING) { - this.rotate(getBlockState(), new BlockPos(getBlockPos().getX(), getBlockPos().getY() + FindController('O').getY(), getBlockPos().getZ()), getLevel(), heat/4, true); - return; - } else { - EventTriggerPacket packet = new EventTriggerPacket(600); - CreateNuclear.LOGGER.warn("hum EventTriggerBlock ? {}", packet); - CatnipServices.NETWORK.sendToClientsAround((ServerLevel) level, getBlockPos(), 32, packet); - - this.rotate(getBlockState(), new BlockPos(getBlockPos().getX(), getBlockPos().getY() + FindController('O').getY(), getBlockPos().getZ()), getLevel(), 0, false); - isTotal = false; - return; - } - } else { - this.rotate(getBlockState(), new BlockPos(getBlockPos().getX(), getBlockPos().getY() + FindController('O').getY(), getBlockPos().getZ()), getLevel(), 0, false); - isTotal = false; - return; - } - } - this.notifyUpdate(); } + isExploding = true; + return; } - } - private boolean isEmptyConfiguredPattern() { - return !configuredPattern.isEmpty();// || !configuredPattern.getOrCreateTag().isEmpty(); - } + if (!isEmptyConfiguredPattern()) { + // Deliberately a local, shadowing the field, exactly as on Forge: the field `heat` + // must keep the value handleAssembledState() computed, and is only refreshed there. + int heat = getConfiguredPatternHeat(); + countCoolerRod = getConfiguredPatternCoolerRodCount(); + countFuelRod = getConfiguredPatternFuelRodCount(); + heatBalance = heatCoordinator.calculateHeatBalance(configuredPattern, displayState, level); + } + resolveEntitiesIfNeeded(); - private boolean updateTimers() { - total -= 1; - return total >= 0;//(total/constTotal) >= 0; - } + ReactorInputSnapshot snapshot = ReactorInputSnapshotBuilder.build(level, inputManager, inputFluidManager); + this.displayState = new ReactorDisplayState(snapshot.items(), snapshot.fluids(), snapshot.maxFluidCapacity()); + this.bigFluidStack = snapshot.fluids(); - private ReactorBluePrintData getDefaultReactorBluePrintData() { - return new ReactorBluePrintData( - 0, 0, 0, 0, - new PatternData[0], new PatternData[0] - ); + updateReactorStateVisibility(); + handleAssembledState(); } - private ReactorBluePrintData getReactorBluePrintData() { - return configuredPattern.getOrDefault(CNDataComponents.REACTOR_BLUE_PRINT_DATA, getDefaultReactorBluePrintData()); + + /** + * Rod counts required by the configured pattern. + *

+ * Forge reads {@code countCoolerRod}/{@code countFuelRod} off the blueprint's NBT tag; + * on NeoForge they live in the {@code ReactorBluePrintData} component written by + * {@code ReactorBluePrintMenu#saveData}. + */ + private int getConfiguredPatternCoolerRodCount() { + return getConfiguredPatternData().countCooledRod(); } - private double calculateProgress() { - ReactorBluePrintData data = getReactorBluePrintData(); - countGraphiteRod = data.countGraphiteRod(); - countUraniumRod = data.countUraniumRod(); - graphiteTimer = data.graphiteTime(); - uraniumTimer = data.uraniumTime(); + private int getConfiguredPatternFuelRodCount() { + return getConfiguredPatternData().countFuelRod(); + } - double progressGraphite = countGraphiteRod > 0 - ? (double) graphiteTimer / countGraphiteRod - : 0.0; - double progressUranium = countUraniumRod > 0 - ? (double) uraniumTimer / countUraniumRod - : 0.0; + /** + * Client-side: keep the looping "running" sound alive while the reactor is producing energy. + * Driven by the {@code ACTIVE} blockstate property, which the server recomputes every tick in + * {@link #updateReactorStateVisibility()} and vanilla syncs to the client automatically. + */ + @OnlyIn(Dist.CLIENT) + private void tickRunningSound() { + BlockState state = getBlockState(); + boolean active = state.hasProperty(ReactorControllerBlock.ACTIVE) + && state.getValue(ReactorControllerBlock.ACTIVE); - double tmp = progressGraphite + progressUranium; + if (!active) { + if (runningSound != null) { + runningSound.stopSound(); + runningSound = null; + } + return; + } - return progressGraphite + progressUranium; + if (runningSound == null || runningSound.isStopped()) { + runningSound = new ReactorRunningSoundInstance(level, worldPosition, CNSoundEvents.REACTOR_RUNNING.getMainEvent()); + Minecraft.getInstance().getSoundManager().play(runningSound); + } } - private double calculateHeat(ItemStack input) { - ReactorBluePrintData data = input.getOrDefault(CNDataComponents.REACTOR_BLUE_PRINT_DATA, getDefaultReactorBluePrintData()); - - countGraphiteRod = data.countGraphiteRod(); - countUraniumRod = data.countUraniumRod(); - heat = 0; + // --- extracted sub-steps to keep single responsibility per method --- + private void resolveEntitiesIfNeeded() { + if (!needsToResolveEntities) + return; + List handlers = inputManager.getItemHandlers(level); + CreateNuclear.LOGGER.warn("Resolving inputs after load, handlers found: {}", handlers.size()); + needsToResolveEntities = false; + this.setChanged(); + } - // if more than maxUraniumPerGraphite of the rods are uranium, the reactor will overheat - if (countUraniumRod > countGraphiteRod * maxUraniumPerGraphite) { - overFlowHeatTimer++; - if (overFlowHeatTimer >= overFlowLimiter) { - overHeat++; - overFlowHeatTimer = 0; - if (overFlowLimiter > 2) { - overFlowLimiter--; - } + /** + * Tick logic applied while the reactor is assembled: if it doesn't have + * enough fuel ({@link IReactorHeatUpdateCoordinator#canRun}), only the + * displayed heat is updated (and outputs stopped); otherwise the actual + * heat is calculated, fluid consumed, the item consumption cycle advanced, + * and outputs rotated according to the heat. + */ + private void handleAssembledState() { + if (!heatCoordinator.canRun(configuredPattern, displayState, inputFluidManager, level, isAssembled())) { + heatCoordinator.updateHeatOnly(configuredPattern, displayState, currentFluidStack(), heatBalance, heat, inventory, level, isAssembled()); + if (!outputManager.getBlocksPosition(getLevel()).isEmpty()) { + outputManager.rotateOutputs(getLevel(), getAssembled(), 0); } - } else { - overFlowHeatTimer = 0; - overFlowLimiter = 30; - overHeat = Math.max(0, overHeat - 2); + + setChanged(); + notifyUpdate(); + return; } - PatternData[] patternDataAll = data.patternAll(); - for (PatternData pd : patternDataAll) { - char currentRod = '\0'; - ItemStack stack = pd.stack(); - - if (stack.is(CNItems.URANIUM_ROD)) { - heat += baseUraniumHeat; - currentRod = 'u'; - } else if (stack.is(CNItems.GRAPHITE_ROD)) { - heat += baseGraphiteHeat; - currentRod = 'g'; - } + setChanged(); + notifyUpdate(); + + BigFluidStack fluidStack = currentFluidStack(); + heat = heatCoordinator.calculateAndWriteHeat(configuredPattern, fluidStack, heatBalance, heat, inventory, level, displayState); + fluidBuffer = fluidRateCalculator.tick(fluidStack, reactorSize, level, inputFluidManager, fluidBuffer); + cycleManager.update(configuredPattern, level, inputManager, level.getGameTime() % 20 == 0); - if (currentRod != '\0') { - pattern: - for (int i = 0; i < formattedPattern.length; i++) { - for (int j = 0; j < formattedPattern[i].length; j++) { - if (formattedPattern[i][j] == pd.slot()) { - // the offsets for the four directions (down, up, right, left) is int[][] offsets = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} }; (defined at the top of the class) - for (int[] offset : offsets) { - int ni = i + offset[0], nj = j + offset[1]; - if (ni < 0 || ni >= formattedPattern.length || nj < 0 || nj >= formattedPattern[i].length) continue; - - int neighborSlot = formattedPattern[ni][nj]; - for (PatternData pd2 : patternDataAll) { - if (pd2.slot() == neighborSlot) { - ItemStack stack2 = pd.stack(); - if (currentRod == 'u') { - heat += stack2.is(CNItems.URANIUM_ROD) ? proximityUraniumHeat : proximityGraphiteHeat; - } - break; - } - } - } - break pattern; - } - } - } + if (IHeat.HeatLevel.isNotDanger(heat, getMultiblockSize()) && !outputManager.getBlocksPosition(level).isEmpty()) { + if (Math.abs(heat - lastAppliedOutputHeat) >= ReactorOutputManager.RPM_DIVIDER / 2) { + lastAppliedOutputHeat = heat; } + outputManager.rotateOutputs(getLevel(), getAssembled(), lastAppliedOutputHeat); } + } - return heat + overHeat; + private boolean isEmptyConfiguredPattern() { + return getConfiguredPatternData() == ReactorBluePrintData.EMPTY; } - private BlockPos getBlockPosForReactor(char character) { - BlockPos pos = FindController(character); - BlockPos posController = getBlockPos(); - BlockPos posInput = new BlockPos(posController.getX(), posController.getY(), posController.getZ()); + public void addInput(BlockPos inputPos) { + this.inputManager.addBlock(inputPos); + this.setChanged(); + } - int[][] directions = { - {0,0, pos.getX()}, // NORTH - {0,0, -pos.getX()}, // SOUTH - {-pos.getX(),0,0}, // EAST - {pos.getX(),0,0} // WEST - }; + public void removeInput(BlockPos inputPos) { + this.inputManager.removeBlock(inputPos); + this.setChanged(); + } + public void addOutput(BlockPos outputPos) { + this.outputManager.addBlock(outputPos); + this.setChanged(); + } - for (int[] direction : directions) { - BlockPos newPos = posController.offset(direction[0], direction[1], direction[2]); - if (level.getBlockState(newPos).is(CNBlocks.REACTOR_INPUT.get())) { - posInput = newPos; - break; - } - } + public void removeOutput(BlockPos outputPos) { + this.outputManager.removeBlock(outputPos); + this.setChanged(); + } - return posInput; - } - - private CompoundTag convertePattern(CompoundTag compoundTag) { - ListTag pattern = compoundTag.getList("Items", Tag.TAG_COMPOUND); - - int[][] list = new int[][]{ - {99,99,99,0,1,2,99,99,99}, - {99,99,3,4,5,6,7,99,99}, - {99,8,9,10,11,12,13,14,99}, - {15,16,17,18,19,20,21,22,23}, - {24,25,26,27,28,29,30,31,32}, - {33,34,35,36,37,38,39,40,41}, - {99,42,43,44,45,46,47,48,99}, - {99,99,49,50,51,52,53,99,99}, - {99,99,99,54,55,56,99,99,99} - }; - - - return null; - } - - private static BlockPos FindController(char character) { - return SimpleMultiBlockAislePatternBuilder.start() - .aisle(AAAAA, AAAAA, AAAAA, AAAAA, AAAAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AAIAA, ADADA, BACAB, ADADA, AAAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AAAAA, AAAAA, AAAAA, AAAAA, AAOAA) - .where('A', a -> a.getState().is(CNBlocks.REACTOR_CASING.get())) - .where('B', a -> a.getState().is(CNBlocks.REACTOR_FRAME.get())) - .where('C', a -> a.getState().is(CNBlocks.REACTOR_CORE.get())) - .where('D', a -> a.getState().is(CNBlocks.REACTOR_COOLER.get())) - .where('*', a -> a.getState().is(CNBlocks.REACTOR_CONTROLLER.get())) - .where('O', a -> a.getState().is(CNBlocks.REACTOR_OUTPUT.get())) - .where('I', a -> a.getState().is(CNBlocks.REACTOR_INPUT.get())) - .getDistanceController(character); - } - - public void rotate(BlockState state, BlockPos pos, Level level, int rotation, boolean isActif) { - rotation = rotation > 0 ? rotation : heat/4; - if (level.getBlockState(pos).is(CNBlocks.REACTOR_OUTPUT.get()) && rotation > 0 && isActif) { - if (level.getBlockState(pos).getBlock() instanceof ReactorOutput block) { - ReactorOutputEntity entity = block.getBlockEntityType().getBlockEntity(level, pos); - if (state.getValue(ASSEMBLED)) { // Starting the energy - entity.speed = rotation; - entity.heat = rotation; - } else { // stopping the energy - entity.speed = 0; - entity.heat = 0; - } - entity.updateSpeed = true; - entity.updateGeneratedRotation(); - entity.setSpeed(rotation); + public void addInputFluid(BlockPos outputPos) { + this.inputFluidManager.addBlock(outputPos); + this.setChanged(); + } - } + public void removeInputFluid(BlockPos outputPos) { + this.inputFluidManager.removeBlock(outputPos); + this.setChanged(); + // Breaking a fluid input discards its tank contents along with the block entity. + // Re-evaluate the fluid lock so a different fluid can be accepted once no remaining + // input still holds liquid — otherwise the controller stays locked to the old fluid. + clearLockIfAllInputsEmpty(); + } + + public void addAlarm(BlockPos alarmPos) { + this.alarmManager.addBlock(alarmPos); + this.setChanged(); + } + + public void removeAlarm(BlockPos alarmPos) { + this.alarmManager.removeBlock(alarmPos); + this.setChanged(); + } + + public void removeIOAll() { + allManagers().forEach(m -> m.clearInvalid(level)); + this.setChanged(); + } + + /** Try to lock this controller to the given Fluid. Returns true if allowed. */ + public boolean tryLockFluid(Fluid fluid) { + // Fluid locks are server-authoritative and persisted per-level via PersistentFluidLocks. + // On the client there is no lock to enforce, so stay permissive. + if (level instanceof ServerLevel serverLevel) { + return PersistentFluidLocks.get(serverLevel).tryLock(getBlockPos(), fluid); } - else { - if (level.getBlockState(pos).getBlock() instanceof ReactorOutput block) { - ReactorOutputEntity entity = block.getBlockEntityType().getBlockEntity(level, pos); - entity.setSpeed(0); - entity.heat = 0; - entity.updateSpeed = true; - entity.updateGeneratedRotation(); - } + return true; + } + + /** Returns whether the given FluidStack is acceptable for this controller. */ + public boolean canAcceptFluid(FluidStack stack) { + if (stack == null || stack.isEmpty()) + return true; + if (level instanceof ServerLevel serverLevel) { + return PersistentFluidLocks.get(serverLevel).canAccept(getBlockPos(), stack.getFluid()); + } + return true; + } + + /** Force-clear the lock on this controller. */ + public void clearLock() { + if (level instanceof ServerLevel serverLevel) { + PersistentFluidLocks.get(serverLevel).clearLock(getBlockPos()); + setChanged(); + sendData(); } } -} \ No newline at end of file + + public void clearLockIfAllInputsEmpty() { + if (level == null || level.isClientSide) + return; + + boolean anyNonEmpty = getInputFluidManager().getFuildHandlers(level).stream() + .anyMatch(handler -> { + for (int t = 0; t < handler.getTanks(); t++) + if (!handler.getFluidInTank(t).isEmpty()) + return true; + return false; + }); + + if (!anyNonEmpty) + clearLock(); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerGenerator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerGenerator.java index 48ac214..618ff0d 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerGenerator.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerGenerator.java @@ -8,6 +8,7 @@ import net.neoforged.neoforge.client.model.generators.ModelFile; public class ReactorControllerGenerator extends SpecialBlockStateGen { + @Override protected int getXRotation(BlockState state) { return 0; @@ -15,11 +16,52 @@ protected int getXRotation(BlockState state) { @Override protected int getYRotation(BlockState state) { + if (state == null || !state.hasProperty(ReactorControllerBlock.FACING)) { + return 0; + } return horizontalAngle(state.getValue(ReactorControllerBlock.FACING)); } @Override public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { - return prov.models().getExistingFile(prov.modLoc("block/reactor/controller/block")); + final String controllerPath = "block/reactor/controller/controller_panel_"; + + // Safety fallback if the state is invalid at the start of Minecraft's block scan + if (!state.hasProperty(ReactorControllerBlock.ASSEMBLED) || !state.hasProperty(ReactorControllerBlock.ACTIVE)) { + return prov.models() + .withExistingParent("block/reactor/controller/" + ControllerVisualState.OFF.getSuffix(), prov.modLoc("block/reactor/controller/block")) + .texture("1", prov.modLoc(controllerPath + ControllerVisualState.OFF.getSuffix())) + .texture("particle", prov.modLoc(controllerPath + ControllerVisualState.OFF.getSuffix())); + } + + boolean isAssembled = state.getValue(ReactorControllerBlock.ASSEMBLED); + boolean isActive = state.getValue(ReactorControllerBlock.ACTIVE); + + ControllerVisualState controllerState = ControllerVisualState.OFF; + if (isAssembled) { + controllerState = isActive ? ControllerVisualState.ON : ControllerVisualState.STANDBY; + } + + return prov.models() + .withExistingParent("block/reactor/controller/" + controllerState.getSuffix(), prov.modLoc("block/reactor/controller/block")) + .texture("1", prov.modLoc(controllerPath + controllerState.getSuffix())) + .texture("particle", prov.modLoc(controllerPath + controllerState.getSuffix())); + } + + enum ControllerVisualState { + OFF("off"), + ON("on"), + STANDBY("standby") + ; + + private final String suffix; + + ControllerVisualState(String suffix) { + this.suffix = suffix; + } + + public String getSuffix() { + return this.suffix; + } } -} \ No newline at end of file +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerInventory.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerInventory.java index 2a43ccd..b518935 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerInventory.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerInventory.java @@ -23,9 +23,6 @@ public ItemStack removeItemNoUpdate(int index) { @Override public boolean isItemValid(int slot, ItemStack resource) { - return switch (slot) { - case 0 -> CNItems.REACTOR_BLUEPRINT.isIn(resource); - default -> !super.isItemValid(slot, resource); - }; + return slot == 0 && resource.is(CNItems.REACTOR_BLUEPRINT.get()); } } \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorDebugDiagnostics.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorDebugDiagnostics.java new file mode 100644 index 0000000..e1e7b74 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorDebugDiagnostics.java @@ -0,0 +1,57 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.*; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; + +import java.util.Collection; + +public class ReactorDebugDiagnostics { + private static final String TITLE = "reactor.debug.title"; + private static final String SUMMARY = "reactor.debug.summary"; + private static final String REGISTERED_POSITION = "reactor.debug.registered_position"; + private static final String VALID_POSITION = "reactor.debug.valid_position"; + + private static final String INPUT = "reactor.debug.label.input"; + private static final String INPUT_FLUID = "reactor.debug.label.fluid_input"; + private static final String OUTPUT = "reactor.debug.label.output"; + private static final String ALARM = "reactor.debug.label.alarm"; + + private ReactorDebugDiagnostics() {} + + public static void sendReactorConnectionsTo(Player player, Level level, + ReactorInputManagerI inputManager, ReactorInputFluidManagerI inputFluidManager, + ReactorOutputManagerI outputManager, + ReactorAlarmManagerI alarmManager + ) { + player.sendSystemMessage(CreateNuclearLang.translate(TITLE).style(ChatFormatting.GOLD).component()); + + sendManagerSummary(player, CreateNuclearLang.translate(INPUT).component(), + inputManager.size(), inputManager.getBlocksPosition(), inputManager.getBlocksPosition(level)); + + sendManagerSummary(player, CreateNuclearLang.translate(INPUT_FLUID).component(), + inputFluidManager.size(), inputFluidManager.getBlocksPosition(), inputFluidManager.getBlocksPosition(level)); + + sendManagerSummary(player, CreateNuclearLang.translate(OUTPUT).component(), + outputManager.size(), outputManager.getBlocksPosition(), outputManager.getBlocksPosition(level)); + + sendManagerSummary(player, CreateNuclearLang.translate(ALARM).component(), + alarmManager.size(), alarmManager.getBlocksPosition(), alarmManager.getBlocksPosition(level)); + } + + private static void sendManagerSummary(Player player, Component label, int registeredCount, + Collection registered, Collection valid) { + player.sendSystemMessage(CreateNuclearLang.translate(SUMMARY, label, registeredCount, valid.size()).style(ChatFormatting.YELLOW).component()); + + for (BlockPos pos : registered) { + player.sendSystemMessage(CreateNuclearLang.translate(REGISTERED_POSITION, pos.toShortString()).component()); + } + for (BlockPos pos : valid) { + player.sendSystemMessage(CreateNuclearLang.translate(VALID_POSITION, pos.toShortString()).component()); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorRunningSoundInstance.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorRunningSoundInstance.java new file mode 100644 index 0000000..52f39cb --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorRunningSoundInstance.java @@ -0,0 +1,61 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller; + +import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance; +import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.nuclearteam.createnuclear.CreateNuclear; + +/** + * Client-side looping sound played while a reactor is actively producing energy. + *

+ * Mirrors {@code ReactorAlarmSoundInstance}: the instance stops itself once the block at + * {@code pos} is no longer a running reactor controller (the {@code ACTIVE} blockstate property + * is synced from the server), so it survives the controller block being broken or the reactor + * shutting down even if the owning block entity's tick stops driving it. + */ +public class ReactorRunningSoundInstance extends AbstractTickableSoundInstance { + private final BlockPos pos; + private final Level level; + + public ReactorRunningSoundInstance(Level level, BlockPos pos, SoundEvent sound) { + super(sound, SoundSource.BLOCKS, level != null ? level.random : null); + this.level = level; + this.pos = pos; + if (pos != null) { + this.x = pos.getX(); + this.y = pos.getY(); + this.z = pos.getZ(); + } + this.looping = true; + this.delay = 0; + this.volume = 1.0F; + } + + @Override + public void tick() { + try { + if (level == null || pos == null) { + stop(); + return; + } + + BlockState state = level.getBlockState(pos); + if (!(state.getBlock() instanceof ReactorControllerBlock) + || !state.hasProperty(ReactorControllerBlock.ACTIVE) + || !state.getValue(ReactorControllerBlock.ACTIVE)) { + stop(); + } + } catch (Exception e) { + stop(); + CreateNuclear.LOGGER.warn(e.getMessage()); + } + } + + /** Public entry point so the owning block entity can stop the loop ({@link #stop()} is protected). */ + public void stopSound() { + stop(); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/ConsumableTimer.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/ConsumableTimer.java new file mode 100644 index 0000000..f668341 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/ConsumableTimer.java @@ -0,0 +1,62 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.consumable; + +import net.minecraft.nbt.CompoundTag; + +public class ConsumableTimer { + private final IConsumable consumable; + private int remainingTicks; + private int maxTicks; + private int countInPattern; + + public ConsumableTimer(IConsumable consumable, int maxTicks, int count) { + this.consumable = consumable; + this.maxTicks = maxTicks; + this.remainingTicks = maxTicks; + this.countInPattern = count; + } + + public boolean tick() { + if (remainingTicks > 0) + remainingTicks--; + return remainingTicks <= 0; + } + + public void reset(int newMaxTicks, int newCount) { + this.maxTicks = newMaxTicks; + this.remainingTicks = newMaxTicks; + this.countInPattern = newCount; + } + + public IConsumable getConsumable() { + return consumable; + } + + public String getId() { + return consumable.getId(); + } + + public int getCountInPattern() { + return countInPattern; + } + + public int getMaxTicks() { + return maxTicks; + } + + public CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + tag.put("consumable", consumable.serializeNBT()); + tag.putInt("remainingTicks", remainingTicks); + tag.putInt("maxTicks", maxTicks); + tag.putInt("countInPattern", countInPattern); + return tag; + } + + public static ConsumableTimer deserializeNBT(CompoundTag tag) { + IConsumable consumable = IConsumable.deserializeNBT(tag.getCompound("consumable")); + ConsumableTimer t = new ConsumableTimer( + consumable, tag.getInt("maxTicks"), tag.getInt("countInPattern")); + t.remainingTicks = tag.getInt("remainingTicks"); + return t; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/ConsumptionCycleManager.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/ConsumptionCycleManager.java new file mode 100644 index 0000000..bfe124a --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/ConsumptionCycleManager.java @@ -0,0 +1,163 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.consumable; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.CNDataComponents; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; +import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintData; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputManagerI; + +import java.util.*; + +public class ConsumptionCycleManager { + + private final List timers = new ArrayList<>(); + private Map patternSnapshot = new HashMap<>(); + + public void startCycle(ItemStack pattern, Level level) { + timers.clear(); + buildTimers(pattern, level); + takeSnapshot(pattern, level); + } + + public void resetCycle(ItemStack pattern, Level level, ReactorInputManagerI manager) { + Map counts = PatternReader.readItemCounts(pattern, level); + List updated = new ArrayList<>(); + + for (Map.Entry entry : counts.entrySet()) { + RodType rodType = RodType.resolveRodType(entry.getKey(), level); + if (!rodType.isNotEmptyItem()) + continue; + + String id = BuiltInRegistries.ITEM.getKey(entry.getKey()).getPath(); + int count = entry.getValue(); + int ticks = new ItemConsumable(id, rodType).computeTimer(count); + + timers.stream() + .filter(t -> t.getId().equals(id)) + .findFirst() + .ifPresentOrElse( + existing -> { + existing.reset(ticks, count); + updated.add(existing); + }, + () -> updated.add(new ConsumableTimer( + new ItemConsumable(id, rodType), ticks, count))); + } + + timers.clear(); + timers.addAll(updated); + takeSnapshot(pattern, level); + } + + public boolean tick(ReactorInputManagerI manager, Level level) { + boolean consumed = false; + Iterator it = timers.iterator(); + + while (it.hasNext()) { + ConsumableTimer timer = it.next(); + if (timer.tick()) { + timer.getConsumable().consume(manager, level); + consumed = true; + + if (timer.getCountInPattern() > 1) { + timer.reset(timer.getMaxTicks(), timer.getCountInPattern()); + } else { + it.remove(); + } + } + } + return consumed; + } + + public boolean hasPatternChanged(ItemStack pattern, Level level) { + Map current = readItemIds(pattern, level); + if (current.size() != patternSnapshot.size()) + return true; + for (Map.Entry e : current.entrySet()) + if (!e.getValue().equals(patternSnapshot.get(e.getKey()))) + return true; + return false; + } + + public boolean isEmpty() { + return timers.isEmpty(); + } + + public void clear() { + timers.clear(); + patternSnapshot.clear(); + } + + public CompoundTag serializeNBT() { + ListTag list = new ListTag(); + timers.forEach(t -> list.add(t.serializeNBT())); + CompoundTag tag = new CompoundTag(); + tag.put("timers", list); + CompoundTag snap = new CompoundTag(); + patternSnapshot.forEach(snap::putInt); + tag.put("snapshot", snap); + return tag; + } + + public void deserializeNBT(CompoundTag tag) { + timers.clear(); + tag.getList("timers", Tag.TAG_COMPOUND) + .forEach(t -> timers.add(ConsumableTimer.deserializeNBT((CompoundTag) t))); + CompoundTag snap = tag.getCompound("snapshot"); + snap.getAllKeys().forEach(k -> patternSnapshot.put(k, snap.getInt(k))); + } + + private void buildTimers(ItemStack pattern, Level level) { + PatternReader.readItemCounts(pattern, level).forEach((item, count) -> { + RodType rodType = RodType.resolveRodType(item, level); + if (!rodType.isNotEmptyItem()) + return; + String id = BuiltInRegistries.ITEM.getKey(item).getPath(); + int ticks = new ItemConsumable(id, rodType).computeTimer(count); + timers.add(new ConsumableTimer(new ItemConsumable(id, rodType), ticks, count)); + }); + } + + private void takeSnapshot(ItemStack pattern, Level level) { + patternSnapshot = readItemIds(pattern, level); + } + + private Map readItemIds(ItemStack pattern, Level level) { + Map result = new HashMap<>(); + PatternReader.readItemCounts(pattern, level).forEach((item, count) -> { + RodType rt = RodType.resolveRodType(item, level); + if (rt.isNotEmptyItem()) + result.put(BuiltInRegistries.ITEM.getKey(item).getPath(), count); + }); + return result; + } + + /** + * Advances the consumption cycle by one tick: starts a cycle if none is + * running and the pattern isn't empty, resets it if the pattern changed + * (only checked when {@code checkPatternChange} is true), then ticks the + * current cycle. + * + * @param checkPatternChange if {@code false}, the pattern change isn't + * checked this tick (used to throttle the check's frequency) + */ + public void update(ItemStack pattern, Level level, ReactorInputManagerI inputManager, boolean checkPatternChange) { + boolean emptyPattern = pattern.getOrDefault(CNDataComponents.REACTOR_BLUE_PRINT_DATA, ReactorBluePrintData.EMPTY) == ReactorBluePrintData.EMPTY; + if (isEmpty() && !emptyPattern) { + startCycle(pattern, level); + } + + if (!isEmpty()) { + if (checkPatternChange && hasPatternChanged(pattern, level)) { + resetCycle(pattern, level, inputManager); + } + tick(inputManager, level); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/FluidConsumable.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/FluidConsumable.java new file mode 100644 index 0000000..be34dc9 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/FluidConsumable.java @@ -0,0 +1,49 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.consumable; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputManagerI; + +public class FluidConsumable implements IConsumable { + private final String fluidName; + private final int mbPerCycle; + private final int baseTicks; + + public FluidConsumable(String fluidName, int mbPerCycle, int baseTicks) { + this.fluidName = fluidName; + this.mbPerCycle = mbPerCycle; + this.baseTicks = baseTicks; + } + + @Override + public String getId() { + return fluidName; + } + + @Override + public int computeTimer(int count) { + return Math.max(1, baseTicks); + } + + @Override + public boolean consume(ReactorInputManagerI manager, Level level) { + return false; + } + + @Override + public CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + tag.putString("type", "fluid"); + tag.putString("fluidName", fluidName); + tag.putInt("mbPerCycle", mbPerCycle); + tag.putInt("baseTicks", baseTicks); + return tag; + } + + public static FluidConsumable deserializeNBT(CompoundTag tag) { + return new FluidConsumable( + tag.getString("fluidName"), + tag.getInt("mbPerCycle"), + tag.getInt("baseTicks")); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/IConsumable.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/IConsumable.java new file mode 100644 index 0000000..21d0ee5 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/IConsumable.java @@ -0,0 +1,24 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.consumable; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputManagerI; + +public interface IConsumable { + String getId(); + + int computeTimer(int countInPattern); + + boolean consume(ReactorInputManagerI manager, Level level); + + CompoundTag serializeNBT(); + + static IConsumable deserializeNBT(CompoundTag tag) { + return switch (tag.getString("type")) { + case "item" -> ItemConsumable.deserializeNBT(tag); + case "fluid" -> FluidConsumable.deserializeNBT(tag); + default -> throw new IllegalArgumentException( + "Unknown consumable type: " + tag.getString("type")); + }; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/ItemConsumable.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/ItemConsumable.java new file mode 100644 index 0000000..556b554 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/ItemConsumable.java @@ -0,0 +1,45 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.consumable; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputManagerI; + +public class ItemConsumable implements IConsumable { + private final String itemName; + private final RodType rodType; + + public ItemConsumable(String itemName, RodType rodType) { + this.itemName = itemName; + this.rodType = rodType; + } + + @Override + public String getId() { + return itemName; + } + + @Override + public int computeTimer(int count) { + int base = Math.max(1, rodType.rodTimer().get()); + return Math.max(1, (int) (base / Math.max(1, count))); + } + + @Override + public boolean consume(ReactorInputManagerI manager, Level level) { + return manager.extractItemByName(level, itemName); + } + + @Override + public CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + tag.putString("type", "item"); + tag.putString("itemName", itemName); + return tag; + } + + public static ItemConsumable deserializeNBT(CompoundTag tag) { + String itemName = tag.getString("itemName"); + return new ItemConsumable(itemName, null); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/PatternReader.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/PatternReader.java new file mode 100644 index 0000000..eae30dc --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/consumable/PatternReader.java @@ -0,0 +1,57 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.consumable; + +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.CNDataComponents; +import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.PatternData; +import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintData; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Reads the rods a configured blueprint asks for, as a count per item. + *

+ * The Forge implementation parsed the raw {@code patternAll}/{@code pattern} NBT + * elements off the blueprint stack. On NeoForge the blueprint carries a typed + * {@link ReactorBluePrintData} data component instead, so the parsing is replaced + * by a read of {@link ReactorBluePrintData#patternAll(Level)}. + *

+ * {@code patternAll} is the normalized view: every empty slot and every non-rod + * item becomes a glass pane, so consumers can assume it only ever holds real rods, + * which is why glass panes are the only value skipped here. Unlike the earlier NBT + * port, it is not stored. {@link ReactorBluePrintData} only persists {@code pattern}, + * the raw grid, and derives {@code patternAll} from it on every call, so the two + * views can no longer diverge on disk. + */ +public final class PatternReader { + + private PatternReader() { + } + + public static Map readItemCounts(ItemStack configuredPattern, Level level) { + if (configuredPattern == null || configuredPattern.isEmpty()) + return Collections.emptyMap(); + + ReactorBluePrintData data = configuredPattern.get(CNDataComponents.REACTOR_BLUE_PRINT_DATA); + if (data == null) + return Collections.emptyMap(); + + PatternData[] slots = data.patternAll(level); + if (slots.length == 0) + return Collections.emptyMap(); + + Map counts = new HashMap<>(); + for (PatternData slot : slots) { + if (slot == null) + continue; + ItemStack stack = slot.stack(); + if (stack != null && !stack.isEmpty() && !stack.is(Items.GLASS_PANE)) + counts.merge(stack.getItem(), 1, Integer::sum); + } + return counts; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorDisplayState.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorDisplayState.java new file mode 100644 index 0000000..ae81082 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorDisplayState.java @@ -0,0 +1,141 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.display; + +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Immutable snapshot of the data the reactor controller exposes for client-side + * display (e.g. the Goggles tooltip rendered by {@code ReactorGoggleTooltipRenderer}). + *

+ * Instances are produced server-side once per tick from the live input inventories + * and tanks, then synced to the client through the block entity's {@code clientPacket} + * NBT via {@link #serializeNBT(HolderLookup.Provider)} / + * {@link #deserializeNBT(HolderLookup.Provider, CompoundTag)}. This data is transient + * sync data only: it is not part of the persisted save NBT, so its layout can evolve + * freely without migration concerns. + *

+ * Usage: + *

{@code
+ * // Server side, e.g. in tick():
+ * this.displayState = new ReactorDisplayState(items, fluids, maxFluidCapacity);
+ *
+ * // Writing the client packet:
+ * compound.put("displayState", displayState.serializeNBT(registries));
+ *
+ * // Reading the client packet:
+ * displayState = compound.contains("displayState")
+ *         ? ReactorDisplayState.deserializeNBT(registries, compound.getCompound("displayState"))
+ *         : ReactorDisplayState.EMPTY;
+ * }
+ * + * @param items item rods currently loaded, mapped to their stacked count + * @param fluids fluids currently loaded in the input tanks + * @param maxFluidCapacity combined capacity (in millibuckets) of all input fluid tanks + */ +public record ReactorDisplayState(Map items, List fluids, long maxFluidCapacity) { + static final String COMPONENT_ITEM = "Item"; + static final String COMPONENT_COUNT = "Count"; + static final String COMPONENT_CLIENT_DISPLAY_ITEMS = "clientDisplayItems"; + static final String COMPONENT_CLIENT_DISPLAY_FLUIDS = "clientDisplayFluids"; + static final String COMPONENT_CLIENT_MAX_FLUIDS_CAPACITY = "clientMaxFluidCapacity"; + + /** + * Shared empty instance, used before the first tick has populated any display + * data and as the fallback when the client packet doesn't carry a display state. + */ + public static final ReactorDisplayState EMPTY = new ReactorDisplayState(Map.of(), List.of(), 0); + + /** + * Defensively copies the given collections so the record stays immutable + * regardless of how the caller's collections are mutated afterwards. + */ + public ReactorDisplayState { + items = Map.copyOf(items); + fluids = List.copyOf(fluids); + } + + /** + * Serializes this state into NBT for inclusion in the block entity's + * {@code clientPacket} data. Pair with + * {@link #deserializeNBT(HolderLookup.Provider, CompoundTag)} to restore an + * equivalent instance on the client. + * + * @param registries registry lookup used to write the contained fluid stacks + * @return a new {@link CompoundTag} containing the serialized item map, + * fluid list and max fluid capacity + */ + public CompoundTag serializeNBT(HolderLookup.Provider registries) { + CompoundTag compound = new CompoundTag(); + + ListTag displayItemsTag = new ListTag(); + for (Entry entry : items().entrySet()) { + CompoundTag tag = new CompoundTag(); + tag.putString(COMPONENT_ITEM, BuiltInRegistries.ITEM.getKey(entry.getKey()).toString()); + tag.putInt(COMPONENT_COUNT, entry.getValue()); + displayItemsTag.add(tag); + } + compound.put(COMPONENT_CLIENT_DISPLAY_ITEMS, displayItemsTag); + + ListTag displayFluidsTag = new ListTag(); + for (BigFluidStack stack : fluids()) { + displayFluidsTag.add(stack.write(registries)); + } + compound.put(COMPONENT_CLIENT_DISPLAY_FLUIDS, displayFluidsTag); + + compound.putLong(COMPONENT_CLIENT_MAX_FLUIDS_CAPACITY, maxFluidCapacity()); + + return compound; + } + + /** + * Reconstructs a {@link ReactorDisplayState} from NBT previously produced by + * {@link #serializeNBT(HolderLookup.Provider)}. Acts as a static factory since + * records cannot be mutated in place. + *

+ * Missing keys are treated as empty/zero, so a compound that contains none of + * the expected entries yields an instance equivalent to {@link #EMPTY}. + * + * @param registries registry lookup used to read the contained fluid stacks + * @param compound the {@code displayState} compound from the client packet + * @return a new immutable {@link ReactorDisplayState} built from the given NBT + */ + public static ReactorDisplayState deserializeNBT(HolderLookup.Provider registries, CompoundTag compound) { + Map items = new HashMap<>(); + if (compound.contains(COMPONENT_CLIENT_DISPLAY_ITEMS)) { + ListTag list = compound.getList(COMPONENT_CLIENT_DISPLAY_ITEMS, Tag.TAG_COMPOUND); + for (int i = 0; i < list.size(); i++) { + CompoundTag tag = list.getCompound(i); + ResourceLocation id = ResourceLocation.tryParse(tag.getString(COMPONENT_ITEM)); + if (id == null) continue; + Item item = BuiltInRegistries.ITEM.getOptional(id).orElse(null); + if (item != null) { + items.put(item, tag.getInt(COMPONENT_COUNT)); + } + } + } + + List fluids = new ArrayList<>(); + if (compound.contains(COMPONENT_CLIENT_DISPLAY_FLUIDS)) { + ListTag list = compound.getList(COMPONENT_CLIENT_DISPLAY_FLUIDS, Tag.TAG_COMPOUND); + for (int i = 0; i < list.size(); i++) { + fluids.add(BigFluidStack.read(registries, list.getCompound(i))); + } + } + + long maxFluidCapacity = compound.getLong(COMPONENT_CLIENT_MAX_FLUIDS_CAPACITY); + + return new ReactorDisplayState(items, fluids, maxFluidCapacity); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorGoggleTooltipRenderer.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorGoggleTooltipRenderer.java new file mode 100644 index 0000000..5b35b06 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorGoggleTooltipRenderer.java @@ -0,0 +1,139 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.display; + +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.IHeat; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; + +import java.util.List; +import java.util.Map; + +/** + * Builds the Goggles tooltip shown when looking at an assembled reactor controller. + *

+ * This is a stateless presentation helper: it only reads from a + * {@link ReactorDisplayState} snapshot (plus the current heat level) and appends the + * resulting lines to the tooltip. It performs no NBT access, inventory lookups or + * other block-entity-specific logic, keeping the rendering separate from the block + * entity's data/state management. + *

+ * Typical usage from {@code ReactorControllerBlockEntity#addToGoggleTooltip}: + *

{@code
+ * @Override
+ * public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) {
+ *     ReactorGoggleTooltipRenderer.render(tooltip, displayState, heat, isPlayerSneaking, reactorSize);
+ *     return true;
+ * }
+ * }
+ */ +public final class ReactorGoggleTooltipRenderer { + private ReactorGoggleTooltipRenderer() {} + + /** + * Appends the reactor controller's Goggles tooltip lines to {@code tooltip}. + *

+ * Renders, in order: the gauge info header, the reactor heat level, the loaded + * item rods (or a placeholder if none), and the loaded fluids with their fill + * ratio as a progress bar (or a placeholder if none). + * + * @param tooltip the tooltip line list to append to + * @param state the current display snapshot (items, fluids, max fluid capacity) + * @param heat the reactor's current heat value, used to render the heat tooltip line + * @param isPlayerSneaking whether the viewing player is sneaking (currently unused, + * kept for signature parity with other goggle tooltip providers) + * @param reactorSize the reactor's multiblock size, used to resolve the heat thresholds + */ + public static void render(List tooltip, ReactorDisplayState state, int heat, boolean isPlayerSneaking, int reactorSize) { + renderHeaderAndHeat(tooltip, heat, reactorSize); + renderItemRods(tooltip, state); + renderFluidTanks(tooltip, state); + } + + /** + * Appends the gauge info header and the reactor's current heat level line. + * + * @param tooltip the tooltip line list to append to + * @param heat the reactor's current heat value + */ + private static void renderHeaderAndHeat(List tooltip, int heat, int reactorSize) { + CreateLang.translate("gui.gauge.info_header") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + IHeat.HeatLevel.getName("reactor_controller").style(ChatFormatting.GRAY).forGoggles(tooltip); + + IHeat.HeatLevel.getFormattedHeatText(heat, reactorSize).forGoggles(tooltip); + } + + /** + * Appends one line per loaded item rod with its stacked count, or a placeholder + * line showing a count of 0 if no rods are loaded. + * + * @param tooltip the tooltip line list to append to + * @param state the current display snapshot + */ + private static void renderItemRods(List tooltip, ReactorDisplayState state) { + if (state.items().isEmpty()) { + CreateNuclearLang.builder() + .add(Component.translatable("createnuclear.tooltip.item.empty.rod").withStyle(ChatFormatting.GRAY)) + .add(CreateNuclearLang.number(0).style(ChatFormatting.GOLD)) + .forGoggles(tooltip); + } else { + for (Map.Entry entry : state.items().entrySet()) { + ItemStack stack = new ItemStack(entry.getKey()); + int count = entry.getValue(); + CreateNuclearLang.itemName(stack) + .style(ChatFormatting.GRAY) + .text(": ") + .add(CreateNuclearLang.number(count).style(ChatFormatting.GOLD)) + .forGoggles(tooltip); + } + } + } + + /** + * Appends one line per loaded fluid with a fill-ratio progress bar relative to + * {@link ReactorDisplayState#maxFluidCapacity()}, or a "no fluid" placeholder + * with an empty progress bar if no fluids are loaded. + * + * @param tooltip the tooltip line list to append to + * @param state the current display snapshot + */ + private static void renderFluidTanks(List tooltip, ReactorDisplayState state) { + if (state.fluids().isEmpty()) { + CreateNuclearLang.translate("tooltip.fluid.none") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + + CreateNuclearLang.builder() + .text(TooltipHelper.makeProgressBar(5, 0)) + .style(ChatFormatting.BLUE) + .space() + .text("0%") + .forGoggles(tooltip); + } else { + long maxCapacity = state.maxFluidCapacity(); + for (BigFluidStack stack : state.fluids()) { + float fillRatio = maxCapacity > 0 ? (float) stack.amount / maxCapacity : 0; + if (fillRatio >= 0.99f) + fillRatio = 1.0f; + int filledBars = Math.round(fillRatio * 5); + + CreateNuclearLang.translate("tooltip.fluid", stack.stack.getHoverName()) + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + + CreateNuclearLang.builder() + .text(TooltipHelper.makeProgressBar(5, filledBars)) + .style(ChatFormatting.BLUE) + .space() + .text(Math.round(fillRatio * 100) + "%") + .forGoggles(tooltip); + } + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/AbstractReactorIOManager.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/AbstractReactorIOManager.java new file mode 100644 index 0000000..b1333cb --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/AbstractReactorIOManager.java @@ -0,0 +1,89 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +/** + * Abstract base providing common implementation for managing + * positions used by IO managers (inputs / outputs). + * + * This class holds a collection of `BlockPos` instances and exposes + * basic operations (add, remove, contains, iteration via `resolveBlock`). + * Serialization (`read`/`write`) and validation (`clearInvalid`) are + * left abstract for concrete implementations to provide. + */ +public abstract class AbstractReactorIOManager implements ReactorIOManager { + /** List of `BlockPos` instances tracked by this manager. */ + protected final List positions = new ArrayList<>(); + + /** + * Adds `pos` if non-null and not already present; returns true when added. + */ + @Override + public void addBlock(BlockPos pos) { + if (pos == null) return; + if (!contains(pos)) { + positions.add(pos); + } + } + + /** + * Removes `pos` if present. + */ + @Override + public void removeBlock(BlockPos pos) { + positions.remove(pos); + } + + /** Tests whether `pos` is present. */ + @Override + public boolean contains(BlockPos pos) { + return positions.contains(pos); + } + + /** Returns the current number of tracked positions. */ + @Override + public int size() { + return positions.size(); + } + + /** Returns an immutable copy of the tracked positions. */ + @Override + public List getBlocksPosition() { + return List.copyOf(positions); + } + + /** + * Resolves each position with `resolver` and returns a list of non-null results. + * Useful to convert positions to block entities or handlers. + */ + @Override + public List resolveBlock(Level level, Function resolver) { + List result = new ArrayList<>(); + for (BlockPos p: new ArrayList<>(positions)) { + T r = resolver.apply(p); + if (r != null) result.add(r); + } + return result; + } + + /** Serialization: implementation provided by subclasses. */ + @Override + public abstract void read(CompoundTag compound); + + /** Deserialization: implementation provided by subclasses. */ + @Override + public abstract void write(CompoundTag compound); + + /** + * Removes invalid positions (e.g. unloaded chunk, missing block entity). + * Subclasses must implement manager-specific validation logic. + */ + @Override + public abstract void clearInvalid(Level level); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorAlarmManager.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorAlarmManager.java new file mode 100644 index 0000000..01fa612 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorAlarmManager.java @@ -0,0 +1,69 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.nuclearteam.createnuclear.content.multiblock.alarm.ReactorAlarmEntity; + +import java.util.ArrayList; +import java.util.List; + +public class ReactorAlarmManager extends AbstractReactorIOManager implements ReactorAlarmManagerI { + private static final String NBT_KEY = "ReactorAlarms"; + + @Override + public void write(CompoundTag compound) { + ListTag list = new ListTag(); + for (BlockPos pos : positions) { + CompoundTag tag = new CompoundTag(); + tag.putInt("x", pos.getX()); + tag.putInt("y", pos.getY()); + tag.putInt("z", pos.getZ()); + list.add(tag); + } + compound.put(NBT_KEY, list); + } + + @Override + public void read(CompoundTag compound) { + positions.clear(); + if (!compound.contains(NBT_KEY)) return; + ListTag list = compound.getList(NBT_KEY, Tag.TAG_COMPOUND); + for (int i = 0; i < list.size(); ++i) { + CompoundTag tag = list.getCompound(i); + positions.add(new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z"))); + } + } + + @Override + public void clearInvalid(Level level) { + if (level == null) return; + List toRemove = new ArrayList<>(); + + for (BlockPos p : positions) { + if (!level.isLoaded(p)) continue; // On ne supprime pas si le chunk est juste déchargé + + BlockEntity be = level.getBlockEntity(p); + if (be == null || !(be instanceof ReactorAlarmEntity)) { + toRemove.add(p); + } + } + positions.removeAll(toRemove); + } + + @Override + public List getBlocksPosition(Level level) { + if (level == null) return List.of(); + + List validPositions = new ArrayList<>(); + for (BlockPos p : this.positions) { + if (level.isLoaded(p) && level.getBlockEntity(p) instanceof ReactorAlarmEntity) { + validPositions.add(p); + } + } + return List.copyOf(validPositions); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorAlarmManagerI.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorAlarmManagerI.java new file mode 100644 index 0000000..e1e154a --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorAlarmManagerI.java @@ -0,0 +1,12 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + +import java.util.List; + +public interface ReactorAlarmManagerI extends ReactorIOManager { + /** * Retourne une copie immuable des positions d'alarmes valides dans le monde actuel. + */ + List getBlocksPosition(Level level); +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorFrameDisplayManager.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorFrameDisplayManager.java new file mode 100644 index 0000000..1ec4369 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorFrameDisplayManager.java @@ -0,0 +1,135 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import org.jetbrains.annotations.Nullable; + +public class ReactorFrameDisplayManager implements ReactorFrameDisplayManagerI { + public static final String COMPONENT_FRAME_COLUMN_MIN_Y = "frameColumnMinY"; + public static final String COMPONENT_FRAME_COLUMN_MAX_Y = "frameColumnMaxY"; + + // Vertical span (block Y) of the reactor frame columns, used to map the + // fluid fill ratio onto the liquid actually drawn in the frame windows. + private int frameColumnMinY = Integer.MAX_VALUE; + private int frameColumnMaxY = Integer.MIN_VALUE; + + // Per-tick cache for the fluid drawn in the frame windows. Recomputed from the + // live (synced) input tanks so the displayed fluid and its fill ratio always + // come from the same source and stay consistent for every fluid type. + private long frameFluidCacheTick = -1; + private float frameFluidFillRatioCache = 0f; + + private FluidStack frameFluidCache = FluidStack.EMPTY; + + /** + * Returns the fluid currently held by the reactor, used by the frame + * renderer to draw the matching liquid in the window. On the client this + * reads the synced ; on the server it reads the + * aggregated . Returns {@link FluidStack#EMPTY} when + * the reactor holds no fluid. + *

+ * Recomputes, at most once per game tick, the fluid shown in the frame + * windows and how full the input is. Both values are read from the same live + * input tanks (whose contents are synced to the client), so they always agree + * regardless of the fluid type. + */ + private void refreshFrameFluidCache(@Nullable Level level, ReactorInputFluidManagerI handlers) { + if (level == null) return; + long now = level.getGameTime(); + + if (now == frameFluidCacheTick) return; + frameFluidCacheTick = now; + + long amount = 0, capacity = 0; + FluidStack fluid = FluidStack.EMPTY; + + for (IFluidHandler handler : handlers.getFuildHandlers(level)) { + int tanks = handler.getTanks(); + for (int t = 0; t < tanks; t++) { + FluidStack stack = handler.getFluidInTank(t); + capacity += handler.getTankCapacity(t); + amount += stack.getAmount(); + + if (fluid.isEmpty() && !stack.isEmpty()) fluid = stack.copy(); + } + } + + frameFluidCache = fluid; + frameFluidFillRatioCache = capacity > 0 ? Math.min(1f, (float) amount / (float) capacity) : 0f; + } + + /** + * The fluid currently shown in the reactor frame windows (may be empty). + */ + @Override + public FluidStack getDisplayedFluid(Level level, ReactorInputFluidManagerI handlers) { + refreshFrameFluidCache(level, handlers); + + return frameFluidCache; + } + + /** + * How full the reactor's fluid input is, in the range {@code [0, 1]}, used by + * the frame renderer to size the visible liquid column. + */ + @Override + public float getDisplayedFluidFillRatio(Level level, ReactorInputFluidManagerI handlers) { + refreshFrameFluidCache(level, handlers); + + return frameFluidFillRatioCache; + } + + /** + * Records the lowest and highest frame block-Y of the assembled reactor. + */ + @Override + public void setFrameColumn(int minY, int maxY, Runnable onChange) { + if (this.frameColumnMinY == minY && this.frameColumnMaxY == maxY) return; + this.frameColumnMinY = minY; + this.frameColumnMaxY = maxY; + onChange.run(); + } + + /** + * @return the lowest frame block-Y, or {@link Integer#MAX_VALUE} if unknown. + */ + @Override + public int getFrameColumnMinY() { + return frameColumnMinY; + } + + /** + * @return the highest frame block-Y, or {@link Integer#MIN_VALUE} if unknown. + */ + @Override + public int getFrameColumnMaxY() { + return frameColumnMaxY; + } + + @Override + public boolean hasFrameColumn() { + return frameColumnMinY != Integer.MAX_VALUE && frameColumnMaxY != Integer.MIN_VALUE + && frameColumnMaxY >= frameColumnMinY; + } + + @Override + public void read(CompoundTag compound) { + if (compound.contains(COMPONENT_FRAME_COLUMN_MIN_Y)) { + frameColumnMinY = compound.getInt(COMPONENT_FRAME_COLUMN_MIN_Y); + } + + if (compound.contains(COMPONENT_FRAME_COLUMN_MAX_Y)) { + frameColumnMaxY = compound.getInt(COMPONENT_FRAME_COLUMN_MAX_Y); + } + } + + @Override + public void write(CompoundTag compound) { + if (hasFrameColumn()) { + compound.putInt(COMPONENT_FRAME_COLUMN_MIN_Y, frameColumnMinY); + compound.putInt(COMPONENT_FRAME_COLUMN_MAX_Y, frameColumnMaxY); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorFrameDisplayManagerI.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorFrameDisplayManagerI.java new file mode 100644 index 0000000..49bfdcf --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorFrameDisplayManagerI.java @@ -0,0 +1,47 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.fluids.FluidStack; + +/** + * Manages the display state of the reactor frame windows: the fluid shown, + * its fill ratio, and the vertical column bounds of the assembled frame. + */ +public interface ReactorFrameDisplayManagerI { + /** + * Returns the fluid currently shown in the reactor frame windows (may be + * empty). Recomputes the underlying cache at most once per game tick from + * the given fluid handlers. + */ + FluidStack getDisplayedFluid(Level level, ReactorInputFluidManagerI handlers); + + /** + * Returns how full the reactor's fluid input is, in the range {@code [0, 1]}. + * Recomputes the underlying cache at most once per game tick from the + * given fluid handlers. + */ + float getDisplayedFluidFillRatio(Level level, ReactorInputFluidManagerI handlers); + + /** + * Records the lowest and highest frame block-Y of the assembled reactor. + * If the values changed, {@code onChange} is invoked (e.g. to trigger a + * client sync via {@code notifyUpdate()}). + */ + void setFrameColumn(int minY, int maxY, Runnable onChange); + + /** @return the lowest frame block-Y, or {@link Integer#MAX_VALUE} if unknown. */ + int getFrameColumnMinY(); + + /** @return the highest frame block-Y, or {@link Integer#MIN_VALUE} if unknown. */ + int getFrameColumnMaxY(); + + /** @return true if both frame column bounds are known and consistent. */ + boolean hasFrameColumn(); + + /** Reads state from an NBT tag (deserialization). */ + void read(CompoundTag compound); + + /** Writes state to an NBT tag (serialization). */ + void write(CompoundTag compound); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorIOManager.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorIOManager.java new file mode 100644 index 0000000..e51f8a9 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorIOManager.java @@ -0,0 +1,49 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; + +import java.util.List; +import java.util.function.Function; + +/** + * Generic manager interface for reactor IO positions (inputs or outputs). + * Defines expected operations to manage a collection of `BlockPos` instances: + * serialization, validation, and resolution into concrete objects via a `resolver`. + */ +public interface ReactorIOManager { + /** Returns true when the position is known. */ + boolean contains(BlockPos pos); + + /** Current number of tracked positions. */ + int size(); + + /** Reads state from an NBT tag (deserialization). */ + void read(CompoundTag compound); + + /** Writes state to an NBT tag (serialization). */ + void write(CompoundTag compound); + + /** + * Adds a position; returns true if added. + */ + void addBlock(BlockPos pos); + + /** + * Removes a position; returns true if it was present and removed. + */ + void removeBlock(BlockPos pos); + + /** Returns an immutable copy of tracked positions. */ + List getBlocksPosition(); + + /** Removes invalid positions for the provided `level` (e.g. missing block entity). */ + void clearInvalid(Level level); + + /** + * Resolves each `BlockPos` into an instance using `resolver` and returns + * the list of non-null results. + */ + List resolveBlock(Level level, Function resolver); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputFluidManager.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputFluidManager.java new file mode 100644 index 0000000..5e37e97 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputFluidManager.java @@ -0,0 +1,169 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.fluids.capability.IFluidHandler.FluidAction; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.ReactorFluidInputEntity; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.VirtualReactorInputFluid; + +import java.util.ArrayList; +import java.util.List; + +public class ReactorInputFluidManager extends AbstractReactorIOManager implements ReactorInputFluidManagerI { + private static final String NBT_KEY = "ReactorInputFluid"; + + /** + * Manager that tracks fluid input blocks for a reactor. + * Responsible for serializing tracked positions, validating + * handlers, reporting aggregated inventory and extracting fluids. + */ + + @Override + /** + * Read tracked positions from NBT data. + * Existing positions are cleared before reading. + */ + public void read(CompoundTag compound) { + positions.clear(); + if (!compound.contains(NBT_KEY)) return; + ListTag list = compound.getList(NBT_KEY, Tag.TAG_COMPOUND); + for (int i = 0; i < list.size(); ++i) { + CompoundTag tag = list.getCompound(i); + positions.add(new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z"))); + } + } + + @Override + /** + * Write tracked positions to the provided NBT compound. + */ + public void write(CompoundTag compound) { + ListTag list = new ListTag(); + for (BlockPos pos : positions) { + CompoundTag tag = new CompoundTag(); + tag.putInt("x", pos.getX()); + tag.putInt("y", pos.getY()); + tag.putInt("z", pos.getZ()); + list.add(tag); + } + compound.put(NBT_KEY, list); + } + + @Override + /** + * Remove any tracked positions that are no longer valid in the given level. + */ + public void clearInvalid(Level level) { + List toRemove = new ArrayList<>(); + for (BlockPos p: positions) { + if (level == null || !level.isLoaded(p)) { + toRemove.add(p); + continue; + } + + BlockEntity be = level.getBlockEntity(p); + if (be == null) { + toRemove.add(p); + continue; + } + + IFluidHandler cap = level.getCapability(Capabilities.FluidHandler.BLOCK, p, null); + if (cap == null) toRemove.add(p); + } + + positions.removeAll(toRemove); + } + + @Override + /** + * Return an immutable list of tracked block positions that correspond + * to fluid input entities in the given level. + */ + public List getBlocksPosition(Level level) { + List positions = new ArrayList<>(); + + for (BlockPos p : this.getBlocksPosition()) { + if (level.getBlockEntity(p) instanceof ReactorFluidInputEntity) positions.add(p); + } + return List.copyOf(positions); + } + + @Override + /** + * Collect and return fluid handler capabilities for all tracked positions. + */ + public List getFuildHandlers(Level level) { + List handlers = new ArrayList<>(); + for (BlockPos p : new ArrayList<>(positions)) { + if (level == null || !level.isLoaded(p)) continue; + BlockEntity be = level.getBlockEntity(p); + if (be == null) continue; + IFluidHandler cap = level.getCapability(Capabilities.FluidHandler.BLOCK, p, null); + if (cap != null) { + handlers.add(cap); + } + } + + return handlers; + } + + @Override + /** + * Build and return a virtual aggregated inventory of all input fluids. + */ + public VirtualReactorInputFluid getInventory(Level level) { + VirtualReactorInputFluid virtualReactorInputFluid = new VirtualReactorInputFluid(); + List handlers = this.getFuildHandlers(level); + if (handlers.isEmpty()) return new VirtualReactorInputFluid(); + + for (IFluidHandler h : handlers) { + virtualReactorInputFluid.addFluid(h.getFluidInTank(0)); + } + + return virtualReactorInputFluid; + } + + /** + * Extracts up to {@code fluidNeeded} units of fluid, spread across the tracked handlers. + *

+ * The requested amount is a TOTAL across every input, not a per-input quota: each handler + * only ever drains what is still missing, so a request of 10 units against two inputs + * holding 10 each removes 10 in total, not 20. + * + * @return {@code true} if at least one unit was actually drained. A partial extraction still + * returns {@code true}: the reactor consumes whatever coolant it can reach rather + * than refusing to run. + */ + @Override + public boolean extractFluids(Level level, int fluidNeeded) { + if (level == null || fluidNeeded <= 0) return false; + List handlers = getFuildHandlers(level); + if (handlers.isEmpty()) return false; + + int remaining = fluidNeeded; + + for (IFluidHandler handler : handlers) { + if (remaining <= 0) break; + + FluidStack stack = handler.getFluidInTank(0); + if (stack.isEmpty()) continue; + + int toExtract = Math.min(remaining, stack.getAmount()); + if (toExtract <= 0) continue; + + // Subtract what was actually drained, not what was asked for: a handler is free to + // hand back less than requested. + remaining -= handler.drain(toExtract, FluidAction.EXECUTE).getAmount(); + } + + return remaining < fluidNeeded; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputFluidManagerI.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputFluidManagerI.java new file mode 100644 index 0000000..6001c7e --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputFluidManagerI.java @@ -0,0 +1,38 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.VirtualReactorInputFluid; + +import java.util.List; + +public interface ReactorInputFluidManagerI extends ReactorIOManager { + /** + * Interface for managing reactor input fluids. + * Implementations track input fluid sources and provide + * accessors and extraction methods for reactor consumption. + */ + /** Returns an immutable copy of tracked positions. */ + List getBlocksPosition(Level level); + + /** + * Returns a list of fluid handler capabilities for the tracked positions. + * @param level the current world level + */ + List getFuildHandlers(Level level); + + /** + * Returns a virtual aggregated inventory representing all tracked input fluids. + * @param level the current world level + */ + VirtualReactorInputFluid getInventory(Level level); + + /** + * Attempt to extract the requested amount of fluid from tracked sources. + * @param level current world level + * @param fluidNeeded amount of fluid required + * @return true if the requested amount was successfully extracted + */ + boolean extractFluids(Level level, int fluidNeeded); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputManager.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputManager.java new file mode 100644 index 0000000..75f52d3 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputManager.java @@ -0,0 +1,195 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.Container; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.items.IItemHandler; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType.TypeRodPredicate; +import net.nuclearteam.createnuclear.content.multiblock.input.item.ReactorRodInputEntity; +import net.nuclearteam.createnuclear.content.multiblock.input.item.VirtualReactorInputsItem; + +import java.util.ArrayList; +import java.util.List; + +/** + * Manager for reactor input positions (`ReactorInput`). + * + * Serializes positions as x/y/z triplets and provides utilities to + * obtain valid `IItemHandler` instances present at those positions. + */ +public class ReactorInputManager extends AbstractReactorIOManager implements ReactorInputManagerI { + private static final String NBT_KEY = "ReactorInput"; + + @Override + public void write(CompoundTag compound) { + ListTag list = new ListTag(); + for (BlockPos pos : positions) { + CompoundTag tag = new CompoundTag(); + tag.putInt("x", pos.getX()); + tag.putInt("y", pos.getY()); + tag.putInt("z", pos.getZ()); + list.add(tag); + } + compound.put(NBT_KEY, list); + } + + @Override + public void read(CompoundTag compound) { + positions.clear(); + if (!compound.contains(NBT_KEY)) return; + ListTag list = compound.getList(NBT_KEY, Tag.TAG_COMPOUND); + for (int i = 0; i < list.size(); ++i) { + CompoundTag tag = list.getCompound(i); + positions.add(new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z"))); + } + } + + /** + * Retrieves all `IItemHandler` instances located at the input positions. + * Returns an empty list when no handlers are found. + */ + @Override + public List getItemHandlers(Level level) { + List handlers = new ArrayList<>(); + for (BlockPos p: new ArrayList<>(positions)) { + if (level == null || !level.isLoaded(p)) continue; + BlockEntity be = level.getBlockEntity(p); + if (be == null) continue; + IItemHandler cap = level.getCapability(Capabilities.ItemHandler.BLOCK, p, null); + if (cap != null) { + handlers.add(cap); + } + } + + return handlers; + } + + @Override + public VirtualReactorInputsItem getInventory(Level level) { + List handlers = this.getItemHandlers(level); + if (handlers.isEmpty()) return new VirtualReactorInputsItem(); + + int totalFuel = 0; + int totalCooler = 0; + for (IItemHandler h : handlers) { + int slots = h.getSlots(); + for (int s = 0; s < slots; s++) { + ItemStack st = h.getStackInSlot(s); + + if (TypeRodPredicate.isFuel(st, level)) totalFuel += st.getCount(); + else if (TypeRodPredicate.isCooled(st, level)) totalCooler += st.getCount(); + } + } + + return new VirtualReactorInputsItem(totalFuel, totalCooler); + } + + @Override + public boolean extractItems(Level level, int fuelNeeded, int coolerNeeded) { + if (level == null) return false; + List handlers = getItemHandlers(level); + if (handlers.isEmpty()) return false; + + int fuelRemaining = fuelNeeded; + int coolerRemaining = coolerNeeded; + + for (IItemHandler handler : handlers) { + int slots = handler.getSlots(); + for (int s = 0; s < slots && (fuelRemaining > 0 || coolerRemaining > 0); s++) { + ItemStack stack = handler.getStackInSlot(s); + if (stack.isEmpty()) continue; + + + if (fuelRemaining > 0 && TypeRodPredicate.isFuel(stack, level)) { + int toExtract = Math.min(fuelRemaining, stack.getCount()); + handler.extractItem(s, toExtract, false); + fuelRemaining -= toExtract; + } else if (coolerRemaining > 0 && TypeRodPredicate.isCooled(stack, level)) { + int toExtract = Math.min(coolerRemaining, stack.getCount()); + handler.extractItem(s, toExtract, false); + coolerRemaining -= toExtract; + } + } + if (fuelRemaining <= 0 && coolerRemaining <= 0) break; + } + + return fuelRemaining <= 0 && coolerRemaining <= 0; + } + + public boolean extractItemByName(Level level, String itemName) { + if (level == null || itemName == null) return false; + + List handlers = getItemHandlers(level); + if (handlers.isEmpty()) return false; + + for (IItemHandler handler : handlers) { + int slots = handler.getSlots(); + for (int s = 0; s < slots; s++) { + ItemStack stack = handler.getStackInSlot(s); + if (stack.isEmpty()) continue; + + // On récupère le nom de l'item (ex: "uranium_rod") + String registryPath = BuiltInRegistries.ITEM.getKey(stack.getItem()).getPath(); + + // Comparaison intelligente : on ignore la casse et les underscores (_) + if (isMatching(registryPath, itemName)) { + // On tente d'extraire 1 unité + ItemStack extracted = handler.extractItem(s, 1, false); + + // Si l'extraction a réussi, on s'arrête là et on renvoie true + if (!extracted.isEmpty()) { + return true; + } + } + } + } + + return false; // On n'a pas trouvé l'item demandé + } + + /** + * Helper pour comparer "GraphiteRod" avec "graphite_rod" + */ + private boolean isMatching(String registryPath, String configName) { + String cleanPath = registryPath.replace("_", "").toLowerCase(); + String cleanConfig = configName.replace("_", "").toLowerCase(); + return cleanPath.equals(cleanConfig); + } + + /** + * Cleans up invalid positions (unloaded chunk, missing block entity, + * or not a `Container`). + */ + @Override + public void clearInvalid(Level level) { + List toRemove = new ArrayList<>(); + for (BlockPos p: positions) { + if (level == null || !level.isLoaded(p)) { + toRemove.add(p); + continue; + } + + BlockEntity be = level.getBlockEntity(p); + if (be == null || !(be instanceof Container)) toRemove.add(p); + } + + positions.removeAll(toRemove); + } + + @Override + public List getBlocksPosition(Level level) { + List positions = new ArrayList<>(); + + for (BlockPos p : this.getBlocksPosition()) { + if (level.getBlockEntity(p) instanceof ReactorRodInputEntity) positions.add(p); + } + return List.copyOf(positions); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputManagerI.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputManagerI.java new file mode 100644 index 0000000..5f1a975 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorInputManagerI.java @@ -0,0 +1,28 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.items.IItemHandler; +import net.nuclearteam.createnuclear.content.multiblock.input.item.VirtualReactorInputsItem; + +import java.util.List; + +/** + * Interface exposing operations specific to reactor inputs. + * Currently provides access to `IItemHandler` instances at resolved input positions. + */ +public interface ReactorInputManagerI extends ReactorIOManager { + /** + * Retrieves valid item handlers for the given `level`. + * May return an empty list if no valid positions exist. + */ + List getItemHandlers(Level level); + + /** Returns an immutable copy of tracked positions. */ + List getBlocksPosition(Level level); + + VirtualReactorInputsItem getInventory(Level level); + + boolean extractItems(Level level, int fuelNeeded, int coolerNeeded); + boolean extractItemByName(Level level, String itemName); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorOutputManager.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorOutputManager.java new file mode 100644 index 0000000..cb6616a --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorOutputManager.java @@ -0,0 +1,114 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutput; +import net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutputEntity; + +import java.util.ArrayList; +import java.util.List; + +/** + * Manager for a reactor's outputs (`ReactorOutput`). + * Handles serialization of output positions. + */ +public class ReactorOutputManager extends AbstractReactorIOManager implements ReactorOutputManagerI { + private static final String NBT_KEY = "ReactorOutputs"; + public static final int RPM_DIVIDER = 32; + + @Override + public void write(CompoundTag compound) { + ListTag list = new ListTag(); + for (BlockPos p : positions) { + CompoundTag t = new CompoundTag(); + t.putLong("p", p.asLong()); + list.add(t); + } + compound.put(NBT_KEY, list); + } + + @Override + public void read(CompoundTag compound) { + positions.clear(); + if (!compound.contains(NBT_KEY)) return; + ListTag list = compound.getList(NBT_KEY, 10); + for (int i = 0; i < list.size(); i++) { + BlockPos p = BlockPos.of(list.getCompound(i).getLong("p")); + positions.add(p); + } + } + + /** + * {@inheritDoc} + * A tracked position is dropped if its chunk isn't loaded or the block + * entity at that position is no longer a {@link ReactorOutputEntity}. + */ + @Override + public void clearInvalid(Level level) { + List toRemove = new ArrayList<>(); + for (BlockPos p : positions) { + if (level == null || !level.isLoaded(p)) { + toRemove.add(p); + continue; + } + BlockEntity be = level.getBlockEntity(p); + if (!(be instanceof ReactorOutputEntity)) toRemove.add(p); + } + positions.removeAll(toRemove); + } + + /** + * {@inheritDoc} + * Filters the tracked positions down to those currently backed by a + * loaded {@link ReactorOutputEntity}. + */ + @Override + public List getBlocksPosition(Level level) { + List positions = new ArrayList<>(); + + for (BlockPos p : this.getBlocksPosition()) { + if (level.getBlockEntity(p) instanceof ReactorOutputEntity) positions.add(p); + } + return List.copyOf(positions); + } + + /** + * {@inheritDoc} + * The total rotation (in RPM, divided down by {@link #RPM_DIVIDER}) is + * split as evenly as possible across the tracked outputs, with the + * remainder distributed to the first outputs. Each output is set to its + * share of the rotation speed if the reactor is assembled, otherwise + * stopped. + */ + @Override + public void rotateOutputs(Level level, boolean assembled, int rotation) { + if (positions.isEmpty()) return; + + int totalRpm = rotation / RPM_DIVIDER; + int size = positions.size(); + int remainingRotation = totalRpm % size; + + for (int i = 0; i < size; i++) { + int dividedRotation = (totalRpm / size) + (i < remainingRotation ? 1 : 0); + BlockPos pos = positions.get(i); + + if (!(level.getBlockState(pos).getBlock() instanceof ReactorOutput block)) continue; + ReactorOutputEntity entity = block.getBlockEntityType().getBlockEntity(level, pos); + if (entity == null) continue; + + if (dividedRotation > 0) { + entity.speed = assembled ? dividedRotation : 0; + entity.updateSpeed = true; + entity.setSpeedAndUpdate(dividedRotation); + entity.updateGeneratedRotation(); + } else { + entity.setSpeedAndUpdate(0); + entity.updateSpeed = true; + entity.updateGeneratedRotation(); + } + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorOutputManagerI.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorOutputManagerI.java new file mode 100644 index 0000000..ddc8b4b --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/manager/ReactorOutputManagerI.java @@ -0,0 +1,20 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.manager; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + +import java.util.List; + +/** + * Interface exposing operations specific to reactor outputs. + */ +public interface ReactorOutputManagerI extends ReactorIOManager { + /** Returns an immutable copy of tracked positions. */ + List getBlocksPosition(Level level); + + /** + * Distributes the total rotation across the tracked outputs and applies + * the corresponding speed/stop to each {@code ReactorOutputEntity}. + */ + void rotateOutputs(Level level, boolean assembled, int rotation); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/DefaultHeatService.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/DefaultHeatService.java new file mode 100644 index 0000000..d066346 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/DefaultHeatService.java @@ -0,0 +1,26 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerInventory; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; +import net.nuclearteam.createnuclear.content.multiblock.reactorLogic.HeatBalance; +import net.nuclearteam.createnuclear.content.multiblock.reactorLogic.HeatManager; + +public class DefaultHeatService implements IHeatService { + private final HeatManager impl; + + public DefaultHeatService(HeatManager impl) { + this.impl = impl; + } + + @Override + public int getLiquidTimer() { + return impl.getLiquidTimer(); + } + + @Override + public double calculateHeat(BigFluidStack bigFluidStack, HeatBalance heatBalance, int previousHeat, ReactorControllerInventory inventory, Level level, ReactorDisplayState displayState) { + return impl.calculateHeat(bigFluidStack, heatBalance, previousHeat, inventory, level, displayState); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/DefaultPersistenceService.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/DefaultPersistenceService.java new file mode 100644 index 0000000..106672a --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/DefaultPersistenceService.java @@ -0,0 +1,51 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; + +public class DefaultPersistenceService implements IPersistenceService { + @Override + public void readBasicState(ReactorControllerBlockEntity owner, CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) { + owner.setMultiblockSize(compound.getInt("reactorSize")); + owner.setMultiblockFacing(Direction.byName(compound.getString("reactorFacing"))); + + owner.setMultiblockStructure(compound.contains("reactorPose") + ? BoundingBox.CODEC.parse(NbtOps.INSTANCE, compound.get("reactorPose")).result().orElse(null) + : null + ); + + if (!clientPacket) { + owner.deserializeInventory(registries, compound.getCompound("pattern")); + } else { + owner.setDisplayState(compound.contains("displayState") + ? ReactorDisplayState.deserializeNBT(registries, compound.getCompound("displayState")) + : ReactorDisplayState.EMPTY + ); + } + owner.setConfiguredPattern(ItemStack.parse(registries, compound.getCompound("items")).orElse(ItemStack.EMPTY)); + + } + + @Override + public void writeBasicState(ReactorControllerBlockEntity owner, CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) { + compound.putInt("reactorSize", owner.getMultiblockSize()); + compound.putString("reactorFacing", owner.getMultiblockFacing() != null ? owner.getMultiblockFacing().getSerializedName() : ""); + if (owner.getMultiblockPos() != null) { + compound.put("reactorPose", BoundingBox.CODEC.encodeStart(NbtOps.INSTANCE, owner.getMultiblockPos()).getOrThrow()); + } + + if (!clientPacket) { + compound.put("pattern", owner.serializeInventory(registries)); + } else { + compound.put("displayState", owner.getDisplayState().serializeNBT(registries)); + } + compound.put("items", owner.getConfiguredPattern().saveOptional(registries)); + + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/FluidConsumptionRateCalculator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/FluidConsumptionRateCalculator.java new file mode 100644 index 0000000..57c48cf --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/FluidConsumptionRateCalculator.java @@ -0,0 +1,52 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputFluidManagerI; + +/** + * Default implementation of {@link IFluidConsumptionRateCalculator}. + * The rate per cycle depends on the fluid's efficiency and the liquid timer + * exposed by {@link IHeatService}, which itself depends on the reactor size. + */ +public class FluidConsumptionRateCalculator implements IFluidConsumptionRateCalculator { + private final IHeatService heatService; + + public FluidConsumptionRateCalculator(IHeatService heatService) { + this.heatService = heatService; + } + + /** + * {@inheritDoc} + * Does nothing if the fluid stack is {@code null} or holds a negligible + * amount (≤ 1). + */ + @Override + public double tick(BigFluidStack fluidStack, int reactorSize, Level level, + ReactorInputFluidManagerI inputFluidManager, double fluidBuffer) { + if (fluidStack == null || fluidStack.amount <= 1) { + return fluidBuffer; + } + + double amountPerCycle = fluidStack.getFluidtype(level).efficiency(); + switch (reactorSize) { + case 5 -> amountPerCycle /= (double) heatService.getLiquidTimer() / 40; + case 7 -> amountPerCycle /= (double) heatService.getLiquidTimer() / 147; + case 9 -> amountPerCycle /= (double) heatService.getLiquidTimer() / 360; + } + + fluidBuffer += amountPerCycle; + + if (fluidBuffer >= 1.0) { + int toExtract = (int) Math.floor(fluidBuffer); + // Known limitation in ReactorInputFluidManager#extractFluids: fluidNeeded is not + // decremented across multiple tracked input handlers, so each handler may drain up + // to toExtract independently (possible over-extraction with several inputs). + // Intentionally left untouched here; out of scope for this calculator. + if (inputFluidManager.extractFluids(level, toExtract)) { + fluidBuffer -= toExtract; + } + } + return fluidBuffer; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IExplosionService.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IExplosionService.java new file mode 100644 index 0000000..13fa188 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IExplosionService.java @@ -0,0 +1,17 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; + +public interface IExplosionService { + void triggerExplosion(ServerLevel level, BlockPos controllerPos, int reactorSize, int countFuelRod, + int notifyRadius, boolean notifyWarnAll); + + default void triggerExplosion(ServerLevel level, BlockPos controllerPos, int reactorSize, int countFuelRod) { + triggerExplosion(level, controllerPos, reactorSize, + countFuelRod, CNConfigs.server().notify.warningDistance.get(), + CNConfigs.server().notify.warnAllPlayers.get() + ); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IFluidConsumptionRateCalculator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IFluidConsumptionRateCalculator.java new file mode 100644 index 0000000..9a9830f --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IFluidConsumptionRateCalculator.java @@ -0,0 +1,25 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputFluidManagerI; + +/** + * Computes how much fluid should be consumed per tick and triggers extraction + * once the accumulated amount reaches a whole unit. + */ +public interface IFluidConsumptionRateCalculator { + + /** + * Advances the consumption calculation by one tick. + * + * @param fluidStack fluid currently loaded, or {@code null} if none + * @param reactorSize reactor size, used to determine the consumption rate + * @param level current level, used to resolve the fluid type + * @param inputFluidManager input manager responsible for extracting the consumed fluid + * @param fluidBuffer fractional remainder accumulated since the previous tick + * @return the new fractional remainder to carry over to the next tick + */ + double tick(BigFluidStack fluidStack, int reactorSize, Level level, + ReactorInputFluidManagerI inputFluidManager, double fluidBuffer); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IHeatService.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IHeatService.java new file mode 100644 index 0000000..ed396bd --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IHeatService.java @@ -0,0 +1,13 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerInventory; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; +import net.nuclearteam.createnuclear.content.multiblock.reactorLogic.HeatBalance; + +public interface IHeatService { + int getLiquidTimer(); + + double calculateHeat(BigFluidStack bigFluidStack, HeatBalance heatBalance, int previousHeat, ReactorControllerInventory inventory, Level level, ReactorDisplayState displayState); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IPersistenceService.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IPersistenceService.java new file mode 100644 index 0000000..c43f400 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IPersistenceService.java @@ -0,0 +1,18 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; + +/** + * Reads and writes the controller's own state (multiblock size/facing/bounds, + * blueprint stack, and either the inventory or the client display snapshot). + *

+ * Both methods take a {@link HolderLookup.Provider} on top of the Forge + * signature: from 1.21 onwards, serializing an {@code ItemStack} or a + * {@code FluidStack} requires registry access. + */ +public interface IPersistenceService { + void readBasicState(ReactorControllerBlockEntity owner, CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket); + void writeBasicState(ReactorControllerBlockEntity owner, CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IReactorAlarmCoordinator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IReactorAlarmCoordinator.java new file mode 100644 index 0000000..f83fe12 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IReactorAlarmCoordinator.java @@ -0,0 +1,29 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorAlarmManagerI; + +/** + * Classifies the reactor's heat into a danger flag and drives the + * {@link net.nuclearteam.createnuclear.content.multiblock.alarm.ReactorAlarm} blocks + * registered in a {@link ReactorAlarmManagerI} accordingly. + */ +public interface IReactorAlarmCoordinator { + + /** + * @param heat the heat value to classify + * @param multiblockSize the reactor's multiblock size, used to resolve the danger threshold + * @return {@code true} if {@code heat} falls in the DANGER heat-level range + */ + boolean computeDanger(int heat, int multiblockSize); + + /** + * Powers on/off every alarm block known to {@code alarmManager} to match {@code isDanger}, + * and awards the SILENCE_THE_CORE advancement on the rising edge (alarm turning on). + * + * @param level the reactor's level + * @param alarmManager the manager holding the alarm block positions + * @param isDanger whether the alarms should be powered on + */ + void update(Level level, ReactorAlarmManagerI alarmManager, boolean isDanger); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IReactorHeatUpdateCoordinator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IReactorHeatUpdateCoordinator.java new file mode 100644 index 0000000..789dd78 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IReactorHeatUpdateCoordinator.java @@ -0,0 +1,87 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerInventory; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputFluidManagerI; +import net.nuclearteam.createnuclear.content.multiblock.reactorLogic.HeatBalance; + +/** + * Centralizes the reactor's heat calculation logic and the decision of + * whether it has enough fuel to run. + *

+ * The {@link HeatBalance} consumed by {@link #updateHeatOnly} and + * {@link #calculateAndWriteHeat} is produced upstream by + * {@link #calculateHeatBalance}; callers resolve it once per tick and pass + * the result into both methods below. + *

+ * Both write methods store the resulting heat on the blueprint stack through + * the {@code CNDataComponents.HEAT} data component. The Forge implementation + * mutated the stack's NBT tag in place; that has no NeoForge equivalent, + * because reading the tag back yields a defensive copy. + */ +public interface IReactorHeatUpdateCoordinator { + + /** + * Computes the pattern's fuel/cooler heat balance (see {@link HeatBalance}), + * used to determine whether the reactor is within the wiki-reference 6:1 + * fuel:cooler equilibrium. + * + * @param configuredPattern the blueprint's configured pattern (required items) + * @param displayState snapshot of items/fluids currently available to the reactor, may be {@code null} + * @param level the level the reactor is in, used to resolve rod types + * @return the resolved heat balance for the pattern + */ + HeatBalance calculateHeatBalance(ItemStack configuredPattern, ReactorDisplayState displayState, Level level); + + /** + * Determines whether the reactor has enough fuel (FUEL-type rods) to start, + * on top of being assembled and having a fluid input. + * + * @param configuredPattern the blueprint's configured pattern (required items) + * @param displayState snapshot of items/fluids currently available to the reactor, may be {@code null} + * @param inputFluidManager the reactor's fluid input manager, used to check that at least one input exists + * @param level the level the reactor is in, used to resolve rod types + * @param assembled whether the multiblock is currently assembled + * @return {@code true} if every fuel rod required by the pattern is + * available and at least one fuel rod is required + */ + boolean canRun(ItemStack configuredPattern, ReactorDisplayState displayState, + ReactorInputFluidManagerI inputFluidManager, Level level, boolean assembled); + + /** + * Updates the heat without running the reactor (case where it isn't ready). + * Heat is only calculated if the full pattern (every required item, not + * just fuel) is available; otherwise it drops back to zero. + * + * @param configuredPattern the blueprint's configured pattern (required items) + * @param displayState snapshot of items/fluids currently available to the reactor, may be {@code null} + * @param fluidStack the reactor's current coolant fluid stack, may be {@code null} + * @param heatBalance the pattern's fuel/cooler heat balance for this tick + * @param previousHeat the heat value calculated on the previous tick + * @param inventory the reactor controller's inventory, used to read the configured pattern items + * @param level the level the reactor is in + * @param assembled whether the multiblock is currently assembled + * @return the calculated heat, also written to the configured pattern's heat component + */ + int updateHeatOnly(ItemStack configuredPattern, ReactorDisplayState displayState, BigFluidStack fluidStack, + HeatBalance heatBalance, int previousHeat, ReactorControllerInventory inventory, Level level, boolean assembled); + + /** + * Calculates the reactor's heat during normal operation and writes it to + * the configured pattern's heat component. + * + * @param configuredPattern the blueprint's configured pattern (required items) + * @param fluidStack the reactor's current coolant fluid stack, may be {@code null} + * @param heatBalance the pattern's fuel/cooler heat balance for this tick + * @param previousHeat the heat value calculated on the previous tick + * @param inventory the reactor controller's inventory, used to read the configured pattern items + * @param level the level the reactor is in + * @param displayState snapshot of items/fluids currently available to the reactor, may be {@code null} + * @return the calculated heat + */ + int calculateAndWriteHeat(ItemStack configuredPattern, BigFluidStack fluidStack, HeatBalance heatBalance, int previousHeat, + ReactorControllerInventory inventory, Level level, ReactorDisplayState displayState); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IReactorMeltdownMonitor.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IReactorMeltdownMonitor.java new file mode 100644 index 0000000..a326391 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/IReactorMeltdownMonitor.java @@ -0,0 +1,31 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; + +/** + * Tracks the reactor's meltdown countdown and the player notifications tied to it. + * Consumes the danger flag computed by {@link IReactorAlarmCoordinator#computeDanger} + * instead of recomputing it, so the heat-level classification stays in a single place. + */ +public interface IReactorMeltdownMonitor { + + /** + * Outcome of a single countdown tick. + * {@code NONE} - not in danger, countdown reset to zero. + * {@code CRITICAL} - in danger, countdown running, explosion threshold not reached yet. + * {@code EXPLODE} - countdown threshold reached, the caller must trigger the explosion now. + */ + enum MeltdownState { NONE, CRITICAL, EXPLODE } + + /** + * Advances the countdown by one tick and sends the matching player notifications + * (stabilized / overheating / meltdown flash / critical failure). + * + * @param level the reactor's level, used for notifications and game time + * @param pos the controller's position, used as the notification origin + * @param isDanger whether the reactor is currently at heat level DANGER + * @return the resulting {@link MeltdownState} for this tick + */ + MeltdownState tick (Level level, BlockPos pos, boolean isDanger); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorAlarmCoordinator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorAlarmCoordinator.java new file mode 100644 index 0000000..4b36543 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorAlarmCoordinator.java @@ -0,0 +1,44 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.nuclearteam.createnuclear.content.multiblock.IHeat; +import net.nuclearteam.createnuclear.content.multiblock.alarm.ReactorAlarm; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorAlarmManagerI; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancement; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancementBehaviour; + +/** + * Default {@link IReactorAlarmCoordinator}. Extracted from + * {@code ReactorControllerBlockEntity.activateAlarms(boolean)}: the alarm wiring and + * advancement award are unchanged from the original implementation. + */ +public class ReactorAlarmCoordinator implements IReactorAlarmCoordinator { + private final CNAdvancementBehaviour advancement; + + public ReactorAlarmCoordinator(CNAdvancementBehaviour advancement) { + this.advancement = advancement; + } + + @Override + public boolean computeDanger(int heat, int multiblockSize) { + return IHeat.HeatLevel.of(heat, multiblockSize) == IHeat.HeatLevel.DANGER; + } + + @Override + public void update(Level level, ReactorAlarmManagerI alarmManager, boolean isDanger) { + if (alarmManager == null) return; + + for (BlockPos pos : alarmManager.getBlocksPosition(level)) { + if (!level.isLoaded(pos)) continue; + + BlockState state = level.getBlockState(pos); + + if (state.getBlock() instanceof ReactorAlarm && state.getValue(ReactorAlarm.POWERED) != isDanger) { + level.setBlock(pos, state.setValue(ReactorAlarm.POWERED, isDanger), 3); + if (isDanger) advancement.awardPlayer(CNAdvancement.SILENCE_THE_CORE); + } + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorHeatUpdateCoordinator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorHeatUpdateCoordinator.java new file mode 100644 index 0000000..505ef7b --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorHeatUpdateCoordinator.java @@ -0,0 +1,153 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.CNDataComponents; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintData; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerInventory; +import net.nuclearteam.createnuclear.content.multiblock.controller.consumable.PatternReader; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputFluidManagerI; +import net.nuclearteam.createnuclear.content.multiblock.reactorLogic.HeatBalance; + +import java.util.Collections; +import java.util.Map; + +/** + * Default implementation of {@link IReactorHeatUpdateCoordinator}. + * Delegates raw heat calculation to {@link IHeatService} and only adds the + * pattern-availability logic (fuel-only vs. full pattern). + */ +public class ReactorHeatUpdateCoordinator implements IReactorHeatUpdateCoordinator { + private final IHeatService heatService; + + public ReactorHeatUpdateCoordinator(IHeatService heatService) { + this.heatService = heatService; + } + + /** + * A blueprint counts as unconfigured when it carries no + * {@link ReactorBluePrintData}. Replaces the Forge check on an empty NBT tag. + */ + private static boolean isEmptyPattern(ItemStack configuredPattern) { + return configuredPattern.getOrDefault(CNDataComponents.REACTOR_BLUE_PRINT_DATA, ReactorBluePrintData.EMPTY) == ReactorBluePrintData.EMPTY; + } + + /** + * Stores the computed heat on the blueprint stack. + *

+ * The Forge original wrote into {@code configuredPattern.getOrCreateTag()}, + * mutating the stack's tag in place. On NeoForge the equivalent read returns a + * defensive copy, so the write has to go through the typed data component or it + * would be silently discarded and the heat would stay pinned at zero. + */ + private static void writeHeat(ItemStack configuredPattern, int heat) { + if (configuredPattern.isEmpty()) return; + configuredPattern.set(CNDataComponents.HEAT, (float) heat); + } + + @Override + public HeatBalance calculateHeatBalance(ItemStack configuredPattern, ReactorDisplayState displayState, Level level) { + Map patternCounts = PatternReader.readItemCounts(configuredPattern, level); + Map currentItems = displayState != null && displayState.items() != null + ? displayState.items() : Collections.emptyMap(); + + int heatPoints = 0; + int coolingPoints = 0; + + for (Map.Entry entry : patternCounts.entrySet()) { + Item item = entry.getKey(); + int requiredCount = entry.getValue(); + int availableCount = currentItems.getOrDefault(item, 0); + int countToUse = Math.min(requiredCount, availableCount); + if (countToUse <= 0) continue; + + RodType rodType = RodType.resolveRodType(item, level); + if (rodType == null || !rodType.isNotEmptyItem()) continue; + + int weighted = rodType.ratio().get() * countToUse; + if (rodType.type() == RodType.TypeRod.FUEL) heatPoints += weighted; + else if (rodType.type() == RodType.TypeRod.COOLER) coolingPoints += weighted; + } + + return new HeatBalance(heatPoints, coolingPoints); + } + + /** Predicate applied to each pattern entry when checking availability. */ + @FunctionalInterface + private interface PatternEntryCheck { + boolean test(Item item, int requiredCount, int availableCount); + } + + /** + * Iterates over the items required by the configured pattern and applies + * {@code check} to each entry, stopping as soon as one entry fails. + * + * @return {@code true} if {@code check} succeeded for every pattern entry + */ + private static boolean checkPatternAvailability(ItemStack configuredPattern, ReactorDisplayState displayState, Level level, + PatternEntryCheck check) { + Map patternCounts = PatternReader.readItemCounts(configuredPattern, level); + Map currentItems = displayState != null && displayState.items() != null + ? displayState.items() : Collections.emptyMap(); + + for (Map.Entry entry : patternCounts.entrySet()) { + Item item = entry.getKey(); + int requiredCount = entry.getValue(); + int availableCount = currentItems.getOrDefault(item, 0); + if (!check.test(item, requiredCount, availableCount)) { + return false; + } + } + return true; + } + + @Override + public boolean canRun(ItemStack configuredPattern, ReactorDisplayState displayState, + ReactorInputFluidManagerI inputFluidManager, Level level, boolean assembled) { + if (isEmptyPattern(configuredPattern) || inputFluidManager.size() == 0 || !assembled) { + return false; + } + + boolean[] hasAnyFuel = {false}; + boolean allFuelAvailable = checkPatternAvailability(configuredPattern, displayState, level, + (item, requiredCount, availableCount) -> { + RodType rodType = RodType.resolveRodType(item, level); + if (rodType.isNotEmptyItem() && rodType.type() == RodType.TypeRod.FUEL) { + hasAnyFuel[0] = true; + return availableCount > 0; + } + return true; // non-fuel entries don't block this gate + } + ); + + return allFuelAvailable && hasAnyFuel[0]; + } + + @Override + public int updateHeatOnly(ItemStack configuredPattern, ReactorDisplayState displayState, BigFluidStack fluidStack, + HeatBalance heatBalance, int previousHeat, ReactorControllerInventory inventory, Level level, boolean assembled) { + int heat = 0; + boolean emptyPattern = isEmptyPattern(configuredPattern); + if (!emptyPattern && assembled) { + boolean allAvailable = checkPatternAvailability(configuredPattern, displayState, level, + (item, requiredCount, availableCount) -> availableCount >= requiredCount); + if (allAvailable) { + heat = (int) heatService.calculateHeat(fluidStack, heatBalance, previousHeat, inventory, level, displayState); + } + } + writeHeat(configuredPattern, heat); + return heat; + } + + @Override + public int calculateAndWriteHeat(ItemStack configuredPattern, BigFluidStack fluidStack, HeatBalance heatBalance, int previousHeat, + ReactorControllerInventory inventory, Level level, ReactorDisplayState displayState) { + int heat = (int) heatService.calculateHeat(fluidStack, heatBalance, previousHeat, inventory, level, displayState); + writeHeat(configuredPattern, heat); + return heat; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorMeltdownExecutor.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorMeltdownExecutor.java new file mode 100644 index 0000000..c957b42 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorMeltdownExecutor.java @@ -0,0 +1,51 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; +import net.minecraft.world.level.GameRules; +import net.nuclearteam.createnuclear.CNEntityType; +import net.nuclearteam.createnuclear.content.explosion.NuclearExplosionEntity; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; +import net.nuclearteam.createnuclear.foundation.utility.NotifyUtil; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.BiomeIrradiationService; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNBiomes; + +public class ReactorMeltdownExecutor implements IExplosionService { + @Override + public void triggerExplosion(ServerLevel level, BlockPos controllerPos, int reactorSize, int countFuelRod, int notifyRadius, boolean notifyWarnAll) { + BlockPos explosionPos = controllerPos.above(5); + + NotifyUtil.sendTitle(level, controllerPos, + CreateNuclearLang.translate("notification.reactor.destroyed"), + CreateNuclearLang.translate("notification.reactor.meltdown_finished"), + ChatFormatting.DARK_RED, notifyRadius, notifyWarnAll, 10, 60, 20 + ); + + float size = computeExplosionSize(reactorSize, countFuelRod); + + NuclearExplosionEntity explosion = new NuclearExplosionEntity(CNEntityType.NUCLEAR_EXPLOSION.get(), level); + explosion.setPos(explosionPos.getX() + 0.5D, explosionPos.getY() + 10.0D, explosionPos.getZ() - 2.0D); + explosion.setSize(size); + explosion.setNoGriefing(!level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)); + level.addFreshEntity(explosion); + + level.destroyBlock(controllerPos, false); + + BiomeIrradiationService.circularArea(level, explosionPos, CNBiomes.Irradiated.PLAIN, (int) (size * 30)); + + } + + private static float computeExplosionSize(int reactorSize, int countFuelRod) { + // Scales with reactor footprint: 5x5 -> 1.0, 7x7 -> 1.4, 9x9 -> 1.8 + float structureFactor = reactorSize / 5f; + + // Square root gives diminishing returns: each extra uranium rod adds less + // to the radius than the previous one. + float fuelImpact = Mth.sqrt(countFuelRod) * .3f; + + // Final size: constant base + (fuel impact scaled by structure factor) + return Mth.clamp(1.5f + (fuelImpact * structureFactor), 1f, 10f); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorMeltdownMonitor.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorMeltdownMonitor.java new file mode 100644 index 0000000..bc75570 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/service/ReactorMeltdownMonitor.java @@ -0,0 +1,67 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.service; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; +import net.nuclearteam.createnuclear.foundation.utility.NotifyUtil; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; + +/** + * Default {@link IReactorMeltdownMonitor}. Extracted from + * {@code ReactorControllerBlockEntity.tick()}: the countdown logic and its notifications + * are unchanged from the original implementation, only moved into their own class. + */ +public class ReactorMeltdownMonitor implements IReactorMeltdownMonitor { + /** Ticks of continuous danger before the reactor explodes (15s at 20 TPS). */ + private static final int EXPLOSION_THRESHOLD_TICKS = 300; + /** Last seconds of the countdown during which the flashing "meltdown in" message is shown. */ + private static final int CRITICAL_WINDOW_SECONDS = 10; + + private int explosionCountDown = 0; + + @Override + public MeltdownState tick(Level level, BlockPos pos, boolean isDanger) { + int configRadius = CNConfigs.server().notify.warningDistance.get(); + boolean configWarnAll = CNConfigs.server().notify.warnAllPlayers.get(); + + if (!isDanger) { + boolean wasCountingDown = explosionCountDown > 0; + explosionCountDown = 0; + if (wasCountingDown) { + NotifyUtil.sendActionBar(level, pos, + CreateNuclearLang.translate("notification.reactor.stabilized"), + ChatFormatting.GREEN, configRadius, configWarnAll); + } + return MeltdownState.NONE; + } + + explosionCountDown++; + int secondsLeft = (EXPLOSION_THRESHOLD_TICKS - explosionCountDown) / 20; + + if (secondsLeft <= CRITICAL_WINDOW_SECONDS && secondsLeft > 0) { + boolean isWhite = (level.getGameTime() / 5) % 2 == 0; + ChatFormatting flashColor = isWhite ? ChatFormatting.WHITE : ChatFormatting.RED; + + NotifyUtil.sendActionBar(level, pos, + CreateNuclearLang.translate("notification.reactor.meltdown_in") + .add(CreateNuclearLang.number(secondsLeft)) + .add(CreateNuclearLang.translate("generic.unit.seconds")), + flashColor, configRadius, configWarnAll); + } else if (secondsLeft > CRITICAL_WINDOW_SECONDS && explosionCountDown % 20 == 0) { + NotifyUtil.sendActionBar(level, pos, + CreateNuclearLang.translate("notification.reactor.overheating"), + ChatFormatting.DARK_RED, configRadius, configWarnAll); + } + + if (explosionCountDown >= EXPLOSION_THRESHOLD_TICKS) { + NotifyUtil.sendTitle(level, pos, + CreateNuclearLang.translate("notification.reactor.critical_failure"), + CreateNuclearLang.translate("notification.reactor.imminent_explosion"), + ChatFormatting.DARK_RED, configRadius, configWarnAll, 0, 40, 10); + return MeltdownState.EXPLODE; + } + + return MeltdownState.CRITICAL; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshot.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshot.java new file mode 100644 index 0000000..b9e5575 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshot.java @@ -0,0 +1,32 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.snapshot; + +import net.minecraft.world.item.Item; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; + +import java.util.List; +import java.util.Map; + +/** + * Snapshot of the reactor's inputs, collected once per tick. + *

+ * {@code items} reflects the items actually present (for tooltip display). + * {@code bigFuelItem}/{@code bigCoolerItem} are derived from + * {@link net.nuclearteam.createnuclear.content.multiblock.input.item.VirtualReactorInputsItem} and always represent, respectively, + * Uranium Rod / Graphite Rod (generic tag-based count, fixed identity) — + * do not use these fields to infer the actual item type loaded. + *

+ * The elements of {@code fluids} ({@link BigFluidStack}) remain mutable + * (public fields); this snapshot only guarantees immutability of the + * list/map structure, not of their contents. + */ + +public record ReactorInputSnapshot(Map items, List fluids, long maxFluidCapacity) { + public static final ReactorInputSnapshot EMPTY = new ReactorInputSnapshot( + Map.of(), List.of(), 0 + ); + + public ReactorInputSnapshot { + items = Map.copyOf(items); + fluids = List.copyOf(fluids); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshotBuilder.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshotBuilder.java new file mode 100644 index 0000000..9396e27 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshotBuilder.java @@ -0,0 +1,49 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.snapshot; + +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.items.IItemHandler; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputFluidManagerI; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputManagerI; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.VirtualReactorInputFluid; +import net.nuclearteam.createnuclear.content.multiblock.input.item.VirtualReactorInputsItem; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ReactorInputSnapshotBuilder { + private ReactorInputSnapshotBuilder() {} + + public static ReactorInputSnapshot build(Level level, ReactorInputManagerI inputManager, ReactorInputFluidManagerI inputFluidManager) { + // Populate display fields for client sync + Map items = new HashMap<>(); + List itemHandlers = inputManager.getItemHandlers(level); + for (IItemHandler h : itemHandlers) { + for (int s = 0; s < h.getSlots(); s++) { + ItemStack st = h.getStackInSlot(s); + if (!st.isEmpty()) { + items.merge(st.getItem(), st.getCount(), Integer::sum); + } + } + } + + long maxFluidCapacity = 0; + for (IFluidHandler h : inputFluidManager.getFuildHandlers(level)) { + if (h.getTanks() > 0) { + maxFluidCapacity += h.getTankCapacity(0); + } + } + + VirtualReactorInputsItem virtualItems = inputManager.getInventory(level); + VirtualReactorInputFluid virtualFluid = inputFluidManager.getInventory(level); + List fluids = VirtualReactorInputFluid.toBigList(virtualFluid.fluids()); + + + + return new ReactorInputSnapshot(items, fluids, maxFluidCapacity); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/cooler/ReactorCooler.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/cooler/ReactorCooler.java new file mode 100644 index 0000000..d046d12 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/cooler/ReactorCooler.java @@ -0,0 +1,39 @@ +package net.nuclearteam.createnuclear.content.multiblock.cooler; + +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.content.multiblock.pattern.ReactorPattern; + +import javax.annotation.Nullable; + +public class ReactorCooler extends Block implements IWrenchable { + public ReactorCooler(Properties properties) { + super(properties); + } + + protected ReactorPattern pattern = new ReactorPattern(); + + @Override // Called when the block is placed on the world + public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { + super.onPlace(state, level, pos, oldState, movedByPiston); + pattern.findController(pos, level, true); + } + + @Override + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity pPlacer, ItemStack stack) { + super.setPlacedBy(level, pos, state, pPlacer, stack); + MultiblockHelpers.handleAdvancedPlacedBy(pos, level, pPlacer); + } + + @Override + public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { + super.onRemove(state, level, pos, newState, movedByPiston); + pattern.findController(pos, level, false); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/core/ReactorCoreEntity.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/core/ReactorCoreEntity.java index e0d4eff..9c38de1 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/core/ReactorCoreEntity.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/core/ReactorCoreEntity.java @@ -1,23 +1,15 @@ package net.nuclearteam.createnuclear.content.multiblock.core; -import lib.multiblock.SimpleMultiBlockAislePatternBuilder; import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import net.nuclearteam.createnuclear.CNBlocks; -import net.nuclearteam.createnuclear.CNDataComponents; -import net.nuclearteam.createnuclear.CreateNuclear; -import net.nuclearteam.createnuclear.content.multiblock.IHeat; import net.nuclearteam.createnuclear.content.multiblock.casing.ReactorCasingEntity; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; -import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; - -import static net.nuclearteam.createnuclear.content.multiblock.CNMultiblock.*; @SuppressWarnings({"unused"}) public class ReactorCoreEntity extends ReactorCasingEntity { + private int countdownTicks = 0; + private boolean hasExploded = false; public ReactorCoreEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); @@ -27,69 +19,6 @@ public ReactorCoreEntity(BlockEntityType type, BlockPos pos, BlockState state public void tick() { super.tick(); - if (level.isClientSide()) return; - - BlockPos controllerPos = getBlockPosForReactor(); - if (level.getBlockEntity(controllerPos) instanceof ReactorControllerBlockEntity reactorController) { - int heat = reactorController.heat; - if (IHeat.HeatLevel.of(heat) == IHeat.HeatLevel.DANGER) { - if (countdownTicks >= CNConfigs.common().explode.time.get()) { // 300 ticks = 15 secondes - explodeReactorCore(level, getBlockPos()); - } else { - countdownTicks++; - } - } else { - countdownTicks = 0; // Reset the countdown if the heat level is not in danger - } - } - } - - private void explodeReactorCore(Level world, BlockPos pos) { - level.explode(null, pos.getX(), pos.getY(), pos.getZ(), 20F, Level.ExplosionInteraction.BLOCK); - } - - private static BlockPos FindController(char character) { - return SimpleMultiBlockAislePatternBuilder.start() - .aisle(AAAAA, AAAAA, AAAAA, AAAAA, AAAAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AAIAA, ADADA, BACAB, ADADA, AAAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AAAAA, AAAAA, AAAAA, AAAAA, AAOAA) - .where('A', a -> a.getState().is(CNBlocks.REACTOR_CASING.get())) - .where('B', a -> a.getState().is(CNBlocks.REACTOR_FRAME.get())) - .where('C', a -> a.getState().is(CNBlocks.REACTOR_CORE.get())) - .where('D', a -> a.getState().is(CNBlocks.REACTOR_COOLER.get())) - .where('*', a -> a.getState().is(CNBlocks.REACTOR_CONTROLLER.get())) - .where('O', a -> a.getState().is(CNBlocks.REACTOR_OUTPUT.get())) - .where('I', a -> a.getState().is(CNBlocks.REACTOR_INPUT.get())) - .getDistanceController(character); - } - - private BlockPos getBlockPosForReactor() { - BlockPos posController = getBlockPos(); - BlockPos posInput = new BlockPos(posController.getX(), posController.getY(), posController.getZ()); - - int[][][] directions = { - {{0, 2, 2}, {0, 1, 2}, {0, 0, 2}, {0, -1, 2}, {0, -2, 2}}, // NORTH - {{0, 2, -2}, {0, 1, -2}, {0, 0, -2}, {0, -1, -2}, {0, -2, -2}}, // SOUTH - - {{2, 2, 0}, {2, 1, 0}, {2, 0, 0}, {2, -1, 0}, {2, -2, 0}}, // EAST - {{-2, 2, 0}, {-2, 1, 0}, {-2, 0, 0}, {-2, -1, 0}, {-2, -2, 0}} // WEST - }; - - - for (int[][] direction : directions) { - for (int[] dir : direction) { - BlockPos newPos = posController.offset(dir[0], dir[1], dir[2]); - if (level.getBlockState(newPos).is(CNBlocks.REACTOR_CONTROLLER.get())) { - posInput = newPos; - break; - } - } - } - - return posInput; + if (level.isClientSide() || hasExploded) return; } } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/fluid/CNReactorFluidTypes.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/fluid/CNReactorFluidTypes.java new file mode 100644 index 0000000..6dac564 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/fluid/CNReactorFluidTypes.java @@ -0,0 +1,54 @@ +package net.nuclearteam.createnuclear.content.multiblock.fluid; + +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.material.Fluids; +import net.nuclearteam.createnuclear.CNFluids; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.CreateNuclearRegistries; +import net.nuclearteam.createnuclear.api.multiblock.fluid.ReactorFluidType; + +import static net.nuclearteam.createnuclear.api.ReactorFluidTypesValue.DEFAULT_REACTOR_FLUID_TYPE; + +public class CNReactorFluidTypes { + /** + * Static registry of reactor fluid types ({@link ReactorFluidType}) for the CreateNuclear mod. + * + *

This class exposes the {@link ResourceKey}s and the {@code bootstrap} + * method invoked by the datapack system to register reactor fluid types used + * by the multiblock (for example, specific fluids with heat/efficiency + * characteristics). The example below shows how to create a + * {@code ReactorFluidType} via its {@code ReactorFluidType.Builder}.

+ * + *

Example — Custom Reactor Fluid:

+ *
{@code
+     * register(ctx, "name", new ReactorFluidType.Builder()
+     *             .maxHeat(int)
+     *             .efficiency(int)
+     *             .fluid(Fluid)
+     *             .build());
+     * }
+ * + * @see ReactorFluidType + * @see CreateNuclearRegistries + */ + public static void bootstrap(BootstrapContext ctx) { + register(ctx, "fallback", DEFAULT_REACTOR_FLUID_TYPE); + register(ctx, "water", new ReactorFluidType.Builder() + .fluid(Fluids.WATER) + .maxHeat(2048) + .efficiency(1000) + .build() + ); + register(ctx, "nitrogen", new ReactorFluidType.Builder() + .fluid(CNFluids.LIQUID_NITROGEN.getSource()) + .maxHeat(8196) + .efficiency(100) + .build() + ); + } + + private static void register(BootstrapContext ctx, String name, ReactorFluidType type) { + ctx.register(ResourceKey.create(CreateNuclearRegistries.FLUID_TYPE, CreateNuclear.asResource(name)), type); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorFrame.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorFrame.java index d9c1ad3..803ada5 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorFrame.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorFrame.java @@ -1,11 +1,11 @@ package net.nuclearteam.createnuclear.content.multiblock.frame; import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; import net.minecraft.util.StringRepresentable; -import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.Level; @@ -13,22 +13,21 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.Property; -import net.nuclearteam.createnuclear.CNBlocks; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock; +import net.nuclearteam.createnuclear.CNBlockEntityTypes; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.content.multiblock.pattern.ReactorPattern; import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - -public class ReactorFrame extends Block implements IWrenchable { +public class ReactorFrame extends Block implements IWrenchable, IBE { public static final Property PART = EnumProperty.create("part", Part.class); - + protected ReactorPattern pattern = new ReactorPattern(); public ReactorFrame(Properties properties) { super(properties); } @@ -108,32 +107,33 @@ public BlockState mirror(BlockState state, Mirror mirror) { @Override public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { super.onPlace(state, level, pos, oldState, movedByPiston); - List players = level.players(); - FindController(pos, level, players, true); + pattern.findController(pos, level, true); } - @Override // called when the player destroys the block, with or without a tool - public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { - super.playerDestroy(level, player, pos, state, blockEntity, tool); - List players = level.players(); - FindController(pos, level, players, false); + + @Override + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @javax.annotation.Nullable LivingEntity pPlacer, ItemStack stack) { + super.setPlacedBy(level, pos, state, pPlacer, stack); + MultiblockHelpers.handleAdvancedPlacedBy(pos, level, pPlacer); } - public ReactorControllerBlock FindController(BlockPos blockPos, Level level, List players, boolean first){ // Function that checks the surrounding blocks in order - BlockPos newBlock; // to find the controller and verify the pattern - Vec3i pos = new Vec3i(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - for (int y = pos.getY()-3; y != pos.getY()+4; y+=1) { - for (int x = pos.getX()-5; x != pos.getX()+5; x+=1) { - for (int z = pos.getZ()-5; z != pos.getZ()+5; z+=1) { - newBlock = new BlockPos(x, y, z); - if (level.getBlockState(newBlock).is(CNBlocks.REACTOR_CONTROLLER.get())) { // verifying the pattern - ReactorControllerBlock controller = (ReactorControllerBlock) level.getBlockState(newBlock).getBlock(); - controller.Verify(level.getBlockState(newBlock), newBlock, level, players, first); - return controller; - } - } - } + @Override + public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { + super.onRemove(state, level, pos, newState, movedByPiston); + // playerDestroy is NOT called in creative mode, so the structure must also be + // re-evaluated here. Only react to an actual block removal/replacement (different + // block type), not to a simple PART property change (same block, via setBlock). + if (!state.is(newState.getBlock())) { + pattern.findController(pos, level, false); } - return null; } + @Override + public Class getBlockEntityClass() { + return ReactorFrameEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return CNBlockEntityTypes.REACTOR_FRAME.get(); + } } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorFrameEntity.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorFrameEntity.java new file mode 100644 index 0000000..893a660 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorFrameEntity.java @@ -0,0 +1,80 @@ +package net.nuclearteam.createnuclear.content.multiblock.frame; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * Block entity for {@link ReactorFrame}. It only stores a reference to the + * reactor controller that owns this frame so the client-side renderer + * ({@link ReactorFrameRenderer}) can fetch the reactor's current fluid and + * draw it dynamically inside the frame window. + * + *

The controller position is assigned by + * {@link net.nuclearteam.createnuclear.content.multiblock.ReactorAssembler} + * during assembly and persisted/synced through {@link SmartBlockEntity}.

+ */ +public class ReactorFrameEntity extends SmartBlockEntity { + + @Nullable + private BlockPos controller; + + public ReactorFrameEntity(BlockEntityType type, BlockPos pos, BlockState state) { + + super(type, pos, state); + setController(pos); + } + + @Override + public void addBehaviours(List behaviours) { } + + /** Assigns the owning reactor controller and syncs the change to clients. */ + public void setController(@Nullable BlockPos controllerPos) { + if (java.util.Objects.equals(this.controller, controllerPos)) return; + this.controller = controllerPos; + notifyUpdate(); + } + + @Nullable + public BlockPos getController() { + return controller; + } + + /** + * Resolves the controller block entity, returning {@code null} when no + * controller is assigned or the referenced block is no longer a controller. + */ + @Nullable + public ReactorControllerBlockEntity getControllerEntity() { + if (controller == null || level == null) return null; + if (level.getBlockEntity(controller) instanceof ReactorControllerBlockEntity controllerEntity) + return controllerEntity; + return null; + } + + @Override + protected void write(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) { + super.write(tag, registries, clientPacket); + if (controller != null) { + tag.putLong("Controller", controller.asLong()); + } + } + + @Override + protected void read(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) { + super.read(tag, registries, clientPacket); + if (tag.contains("Controller")) { + this.controller = BlockPos.of(tag.getLong("Controller")); + } else { + this.controller = null; + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorFrameRenderer.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorFrameRenderer.java new file mode 100644 index 0000000..ce46c08 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorFrameRenderer.java @@ -0,0 +1,83 @@ +package net.nuclearteam.createnuclear.content.multiblock.frame; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import net.createmod.catnip.platform.CatnipServices; +import net.createmod.catnip.render.FluidRenderHelper; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.neoforged.neoforge.fluids.FluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorFrameDisplayManagerI; + +/** + * Renders the reactor fluid dynamically inside the {@link ReactorFrame} window. + * The fluid (texture + tint) is resolved from the owning reactor controller, so + * the visible liquid reflects whichever fluid the reactor actually uses + * (water, liquid nitrogen, ...) instead of a texture baked into the model. + */ +public class ReactorFrameRenderer extends SafeBlockEntityRenderer { + + // Horizontal interior of the window (1..15 px on a 16 px block). + private static final float X_MIN = 1f / 16f; + private static final float X_MAX = 15f / 16f; + private static final float Z_MIN = 1f / 16f; + private static final float Z_MAX = 15f / 16f; + + public ReactorFrameRenderer(BlockEntityRendererProvider.Context context) { } + + @Override + protected void renderSafe(ReactorFrameEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + ReactorControllerBlockEntity controller = be.getControllerEntity(); + if (controller == null) return; + + ReactorFrameDisplayManagerI frameDisplay = controller.getFrameDisplayManager(); + + FluidStack fluid = frameDisplay.getDisplayedFluid(controller.getLevel(), controller.getInputFluidManager()); + if (fluid == null || fluid.isEmpty()) return; + + // Local vertical bounds of the liquid volume inside this block, matching + // what used to be baked into each frame part model + // (frame_top / frame_middle / frame_bottom / frame_none). + float boxYMin; + float boxYMax; + switch (be.getBlockState().getValue(ReactorFrame.PART)) { + case START -> { boxYMin = 0f; boxYMax = 9f / 16f; } + case MIDDLE -> { boxYMin = 0f; boxYMax = 1f; } + case END -> { boxYMin = 4f / 16f; boxYMax = 1f; } + default -> { boxYMin = 2.9f / 16f; boxYMax = 9.9f / 16f; } + } + + // Clamp the liquid to the reactor's global fill level so the whole wall + // shares one continuous surface that rises from the bottom as the input + // fills. The level is mapped over the range that liquid actually occupies: + // from the bottom frame's lip (frameMinY + 4/16) to the top frame's cap + // (frameMaxY + 9/16), so even a nearly-empty reactor still shows a sliver. + float yMax = boxYMax; + if (frameDisplay.hasFrameColumn()) { + float ratio = frameDisplay.getDisplayedFluidFillRatio(controller.getLevel(), controller.getInputFluidManager()); + double liquidBottomWorldY = frameDisplay.getFrameColumnMinY() + 4.0 / 16.0; + double liquidTopWorldY = frameDisplay.getFrameColumnMaxY() + 9.0 / 16.0; + double surfaceWorldY = liquidBottomWorldY + ratio * (liquidTopWorldY - liquidBottomWorldY); + double localSurface = surfaceWorldY - be.getBlockPos().getY(); + if (localSurface <= boxYMin) return; // liquid level is below this block + yMax = (float) Math.min(boxYMax, localSurface); + } + + // Last arg (invertGasses) must be false: liquid nitrogen has density 0, so + // it counts as "lighter than air" and would otherwise be flipped 180°, + // hiding the top surface. We always fill bottom-to-top here. + // Must pass the FluidStack, not fluid.getFluid().defaultFluidState(): the FluidState + // overload resolves the texture and tint from the fluid's block state, which loses the + // stack's tint and renders water almost black in the frame windows. + // CatnipServices.FLUID_RENDERER is declared as FluidRenderHelper, so the platform + // type has to be reintroduced by hand — on NeoForge it is neoforge's FluidStack. + @SuppressWarnings("unchecked") + FluidRenderHelper fluidRenderer = (FluidRenderHelper) CatnipServices.FLUID_RENDERER; + + fluidRenderer.renderFluidBox(fluid, + X_MIN, boxYMin, Z_MIN, X_MAX, yMax, Z_MAX, + buffer, ms, light, false, false); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorGaugeOverrides.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorGaugeOverrides.java deleted file mode 100644 index eed053f..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/frame/ReactorGaugeOverrides.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.nuclearteam.createnuclear.content.multiblock.frame; - -import com.tterrag.registrate.providers.DataGenContext; -import com.tterrag.registrate.providers.RegistrateItemModelProvider; -import net.minecraft.world.item.Item; -import net.neoforged.neoforge.client.model.generators.ItemModelBuilder; - -public class ReactorGaugeOverrides { - public static ItemModelBuilder addOverrideModels(DataGenContext c, RegistrateItemModelProvider p) { - ItemModelBuilder builder = p.generated(c); - /*CreateNuclear.LOGGER.warn(" " + builder.override() - .model(p.getBuilder("block/reactor_main_frame/reactor_gauge_none") - .parent(p.getExistingFile(p.modLoc("block/reactor_main_frame/reactor_gauge_none")))) - .end().toJson());*/ - return builder.override() - .model(p.getBuilder("block/reactor_main_frame/reactor_gauge_none") - .parent(p.getExistingFile(p.modLoc("block/reactor_main_frame/reactor_gauge_none")))) - .end(); - //.predicate(CreateNuclear.asResource("reactor_main_frame"), 0) - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInput.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInput.java deleted file mode 100644 index afe2fd2..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInput.java +++ /dev/null @@ -1,142 +0,0 @@ -package net.nuclearteam.createnuclear.content.multiblock.input; - -import com.simibubi.create.content.equipment.wrench.IWrenchable; -import com.simibubi.create.foundation.block.IBE; -import com.simibubi.create.foundation.item.ItemHelper; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.ItemInteractionResult; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.nuclearteam.createnuclear.CNBlockEntityTypes; -import net.nuclearteam.createnuclear.CNBlocks; -import net.nuclearteam.createnuclear.CNShapes; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; -import net.nuclearteam.createnuclear.foundation.block.HorizontalDirectionalReactorBlock; -import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nullable; -import java.util.List; - -public class ReactorInput extends HorizontalDirectionalReactorBlock implements IWrenchable, IBE { - - public ReactorInput(Properties properties) { - super(properties); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(FACING); - super.createBlockStateDefinition(builder); - } - - @Override - public ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { - ItemStack itemInHand = player.getItemInHand(hand); - - if (itemInHand.getItem() instanceof BlockItem) { - return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; - } - - - if (level.isClientSide()) {return ItemInteractionResult.SUCCESS;} - - withBlockEntityDo(level, pos, be -> player.openMenu(be, be::sendToMenu)); - return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; - } - - @Override - public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { - super.onPlace(state, level, pos, oldState, isMoving); - List players = level.players(); - FindController(pos, level, players, true); - } - - // @Override // ! may be useless - // public void setPlacedBy(Level worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { - // super.setPlacedBy(worldIn, pos, state, placer, stack); - // if (worldIn.isClientSide) - // return; - // if (stack == null) - // return; - // withBlockEntityDo(worldIn, pos, be -> { - // CompoundTag orCreateTag = stack.getOrCreateTag(); - // be.readInventory(orCreateTag.getCompound("Inventory")); - // }); - // } - - @Override - public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { - super.playerDestroy(level, player, pos, state, blockEntity, tool); - List players = level.players(); - FindController(pos, level, players, false); - } - - @Override - public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { - super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving); - - withBlockEntityDo(pLevel, pPos, be -> ItemHelper.dropContents(pLevel, pPos, be.inventory)); - pLevel.removeBlockEntity(pPos); - - List players = pLevel.players(); - FindController(pPos, pLevel, players, false); - } - - public ReactorControllerBlock FindController(BlockPos blockPos, Level level, List players, boolean first){ // Function that checks the surrounding blocks in order - BlockPos newBlock; // to find the controller and verify the pattern - Vec3i pos = new Vec3i(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - for (int x = pos.getX()-5; x != pos.getX()+5; x+=1) { - for (int z = pos.getZ()-5; z != pos.getZ()+5; z+=1) { - newBlock = new BlockPos(x, pos.getY(), z); - if (level.getBlockState(newBlock).is(CNBlocks.REACTOR_CONTROLLER.get())) { // verifying the pattern - ReactorControllerBlock controller = (ReactorControllerBlock) level.getBlockState(newBlock).getBlock(); - controller.Verify(level.getBlockState(newBlock), newBlock, level, players, first); - ReactorControllerBlockEntity entity = controller.getBlockEntity(level, newBlock); - if (entity.created) { - return controller; - } - } - } - } - return null; - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - return this.defaultBlockState() - .setValue(FACING, context.getHorizontalDirection().getOpposite()); - } - @Override - public @NotNull VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { - return CNShapes.REACTOR_INPUT.get(state.getValue(FACING)); - } - - @Override - public Class getBlockEntityClass() { - return ReactorInputEntity.class; - } - - @Override - public BlockEntityType getBlockEntityType() { - return CNBlockEntityTypes.REACTOR_INPUT.get(); - } -} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputEntity.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputEntity.java deleted file mode 100644 index 5e69944..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputEntity.java +++ /dev/null @@ -1,119 +0,0 @@ -package net.nuclearteam.createnuclear.content.multiblock.input; - -import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; -import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import lib.multiblock.SimpleMultiBlockAislePatternBuilder; -import net.minecraft.core.BlockPos; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.neoforged.neoforge.capabilities.Capabilities; -import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; -import net.nuclearteam.createnuclear.CNBlockEntityTypes; -import net.nuclearteam.createnuclear.CNBlocks; - -import javax.annotation.Nullable; -import java.util.List; - -import static net.nuclearteam.createnuclear.content.multiblock.CNMultiblock.*; - -public class ReactorInputEntity extends SmartBlockEntity implements MenuProvider { - protected BlockPos block; - - public ReactorInputInventory inventory; - - - public ReactorInputEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - inventory = new ReactorInputInventory(this); - } - - public static void registerCapabilities(RegisterCapabilitiesEvent event) { - event.registerBlockEntity( - Capabilities.ItemHandler.BLOCK, - CNBlockEntityTypes.REACTOR_INPUT.get(), - (be, context) -> be.inventory - ); - } - - @Override - public void addBehaviours(List behaviours) { } - - @Override - protected void read(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) { - if (!clientPacket) { - inventory.deserializeNBT(registries, tag.getCompound("Inventory")); - } - super.read(tag, registries, clientPacket); - } - - @Override - protected void write(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) { - if (!clientPacket) { - tag.put("Inventory", inventory.serializeNBT(registries)); - } - super.write(tag, registries, clientPacket); - } - - - @Nullable - @Override - public Level getLevel() { - return super.getLevel(); - } - - - private static BlockPos FindController(char character) { - return SimpleMultiBlockAislePatternBuilder.start() - .aisle(AAAAA, AAAAA, AAAAA, AAAAA, AAAAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AAIAA, ADADA, BACAB, ADADA, AAAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AABAA, ADADA, BACAB, ADADA, AABAA) - .aisle(AAAAA, AAAAA, AAAAA, AAAAA, AAOAA) - .where('A', a -> a.getState().is(CNBlocks.REACTOR_CASING.get())) - .where('B', a -> a.getState().is(CNBlocks.REACTOR_FRAME.get())) - .where('C', a -> a.getState().is(CNBlocks.REACTOR_CORE.get())) - .where('D', a -> a.getState().is(CNBlocks.REACTOR_COOLER.get())) - .where('*', a -> a.getState().is(CNBlocks.REACTOR_CONTROLLER.get())) - .where('O', a -> a.getState().is(CNBlocks.REACTOR_OUTPUT.get())) - .where('I', a -> a.getState().is(CNBlocks.REACTOR_INPUT.get())) - .getDistanceController(character); - } - - @Override - public Component getDisplayName() { - return Component.translatable("gui.createnuclear.reactor_input.title"); - } - - @Nullable - @Override - public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { - return ReactorInputMenu.create(i, inventory, this); - } - - @Override - public void tick() { - super.tick(); - } - - - /*protected boolean isItemHandlerCap(Capability cap) { - return cap == ForgeCapabilities.ITEM_HANDLER; - }*/ - - /*@Override - public ResetableLazy getCapability(Capability cap, Direction side) { - if (isItemHandlerCap(cap)) - return inventoryProvider.cast(); - return super.getCapability(cap, side); - }*/ -} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputGenerator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputGenerator.java deleted file mode 100644 index 04c9518..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputGenerator.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.nuclearteam.createnuclear.content.multiblock.input; - -import com.simibubi.create.foundation.data.SpecialBlockStateGen; -import com.tterrag.registrate.providers.DataGenContext; -import com.tterrag.registrate.providers.RegistrateBlockstateProvider; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.neoforged.neoforge.client.model.generators.ModelFile; - -public class ReactorInputGenerator extends SpecialBlockStateGen { - @Override - protected int getXRotation(BlockState state) { - return 0; - } - - @Override - protected int getYRotation(BlockState state) { - return horizontalAngle(state.getValue(ReactorInput.FACING)); - } - - @Override - public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { - return prov.models().getExistingFile(prov.modLoc("block/reactor/input/block")); - } -} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputInventory.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputInventory.java deleted file mode 100644 index dce2c1a..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputInventory.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.nuclearteam.createnuclear.content.multiblock.input; - - -import net.minecraft.world.item.ItemStack; -import net.neoforged.neoforge.items.ItemStackHandler; -import net.nuclearteam.createnuclear.CNItems; -import org.jetbrains.annotations.NotNull; - -public class ReactorInputInventory extends ItemStackHandler { - private final ReactorInputEntity be; - - public ReactorInputInventory(ReactorInputEntity be) { - super(2); - this.be = be; - } - - @Override - protected void onContentsChanged(int slot) { - super.onContentsChanged(slot); - be.setChanged(); - } - - @Override - public boolean isItemValid(int slot, @NotNull ItemStack stack) { - return switch (slot) { - case 0 -> CNItems.URANIUM_ROD.isIn(stack); - case 1 -> CNItems.GRAPHITE_ROD.isIn(stack); - default -> !super.isItemValid(slot, stack); - }; - } -} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputMenu.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputMenu.java deleted file mode 100644 index f042457..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputMenu.java +++ /dev/null @@ -1,103 +0,0 @@ -package net.nuclearteam.createnuclear.content.multiblock.input; - -import com.simibubi.create.foundation.gui.menu.MenuBase; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.ClickType; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.neoforged.neoforge.items.SlotItemHandler; -import net.nuclearteam.createnuclear.CNMenus; - -public class ReactorInputMenu extends MenuBase { - - - public ReactorInputMenu(MenuType type, int id, Inventory inv, RegistryFriendlyByteBuf extraData) { - super(type, id, inv, extraData); - } - - public ReactorInputMenu(MenuType type, int id, Inventory inv, ReactorInputEntity contentHolder) { - super(type, id, inv, contentHolder); - } - - public static ReactorInputMenu create(int id, Inventory inv, ReactorInputEntity contentHolder) { - return new ReactorInputMenu(CNMenus.SLOT_ITEM_STORAGE.get(), id, inv, contentHolder); - } - - @Override - public ItemStack quickMoveStack(Player player, int index) { - Slot clickedSlot = getSlot(index); - if (!clickedSlot.hasItem()) return ItemStack.EMPTY; - ItemStack stack = clickedSlot.getItem(); - if (index < 2) moveItemStackTo(stack, 2, slots.size(), false); - else moveItemStackTo(stack, 0, 2, false); - return ItemStack.EMPTY; - } - - - - @Override - protected ReactorInputEntity createOnClient(RegistryFriendlyByteBuf extraData) { - ClientLevel world = Minecraft.getInstance().level; - BlockEntity blockEntity = world.getBlockEntity(extraData.readBlockPos()); - - if (blockEntity instanceof ReactorInputEntity reactorInput) { - reactorInput.readClient(extraData.readNbt(), extraData.registryAccess()); - return reactorInput; - } - return null; - } - - @Override - protected void initAndReadInventory(ReactorInputEntity contentHolder) { - - } - - @Override - protected void addSlots() { - // player Slots - for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) { - this.addSlot(new Slot(player.getInventory(), hotbarSlot, -31 + hotbarSlot * 18, 155)); - } - - for (int row = 0; row < 3; ++row) { - for (int col = 0; col < 9; ++col) { - this.addSlot(new Slot(player.getInventory(), col + row * 9 + 9, -31 + col * 18, 97 + row * 18)); - } - } - - Slot slot1 = new SlotItemHandler(contentHolder.inventory, 0, 24, 29); - Slot slot2 = new SlotItemHandler(contentHolder.inventory, 1, 57, 29); - - addSlot(slot1); - addSlot(slot2); - - - } - - @Override - protected void saveData(ReactorInputEntity contentHolder) { - } - - @Override - public void clicked(int slotId, int button, ClickType clickType, Player player) { - if (clickType == ClickType.THROW) { - int[] targetSlotIds = {9, 18, 27, 0, 1, 28, 19, 10, 16, 17, 26, 25, 34, 35, 8, 7}; - for (int id : targetSlotIds) { - if (slotId == id) { - clickType = ClickType.PICKUP; - super.clicked(slotId, button, clickType, player); - } - } - return; - } - super.clicked(slotId, button, clickType, player); - } -} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputScreen.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputScreen.java deleted file mode 100644 index 9bd900f..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/ReactorInputScreen.java +++ /dev/null @@ -1,39 +0,0 @@ -package net.nuclearteam.createnuclear.content.multiblock.input; - -import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Inventory; -import net.nuclearteam.createnuclear.foundation.gui.CNGuiTextures; - -import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; - -public class ReactorInputScreen extends AbstractSimiContainerScreen { - - protected static final CNGuiTextures background = CNGuiTextures.REACTOR_SLOT_INVENTOR; - - public ReactorInputScreen(ReactorInputMenu container, Inventory inv, Component title) { - super(container, inv, title); - } - - @Override - protected void init() { - setWindowSize(background.width, background.height+ 4 + AllGuiTextures.PLAYER_INVENTORY.getHeight()); - setWindowOffset(0,0); - super.init(); - } - - @Override - protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) { - int invX = getLeftOfCentered(PLAYER_INVENTORY.getWidth()); - int invY = topPos + background.height + 4; - renderPlayerInventory(guiGraphics, invX, invY); - - int x = leftPos; - int y = topPos; - - background.render(guiGraphics, x, y); - - } -} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/FluidLockManager.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/FluidLockManager.java new file mode 100644 index 0000000..b646651 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/FluidLockManager.java @@ -0,0 +1,38 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.fluid; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.material.Fluid; +import net.neoforged.neoforge.fluids.FluidStack; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * In-memory manager for ephemeral fluid locks on multiblock controllers. + * This class provides simple concurrent lock semantics to ensure a controller + * accepts only a single fluid type while a lock is held. + */ +public class FluidLockManager { + private static final Map locks = new ConcurrentHashMap<>(); + + public static boolean tryLock(BlockPos controllerPos, Fluid fluid) { + if (fluid == null) return true; + // Attempt to set the lock to the specified fluid if none exists + return locks.compute(controllerPos, (k,v) -> v == null ? fluid : v) == fluid; + } + + public static boolean canAccept(BlockPos controllerPos, FluidStack stack) { + if (stack == null || stack.isEmpty()) return true; + // True if no fluid locked or the locked fluid matches the stack + Fluid locked = locks.get(controllerPos); + return locked == null || locked == stack.getFluid(); + } + + public static void clearLock(BlockPos controller) { + locks.remove(controller); + } + + public static Fluid getLockedFluid(BlockPos controller) { + return locks.get(controller); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/PersistentFluidLocks.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/PersistentFluidLocks.java new file mode 100644 index 0000000..8328565 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/PersistentFluidLocks.java @@ -0,0 +1,105 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.fluid; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.saveddata.SavedData; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class PersistentFluidLocks extends SavedData { + private final Map locks = new ConcurrentHashMap<>(); + private static final String DATA_NAME = "createnuclear_fluid_locks"; + + /** + * Persistent storage for fluid locks associated with multiblock controllers. + * Locks are persisted to world saved data so controllers keep their preferred + * fluid across server restarts. + */ + public static SavedData.Factory factory() { + return new SavedData.Factory<>( + PersistentFluidLocks::new, + (tag, registries) -> { + PersistentFluidLocks d = new PersistentFluidLocks(); + d.readFrom(tag); + return d; + } + ); + } + + public static PersistentFluidLocks get(ServerLevel level) { + return level.getDataStorage().computeIfAbsent(PersistentFluidLocks.factory(), DATA_NAME); + } + + /** + * Attempt to acquire a persistent lock for the specified controller position. + * @param pos controller block position + * @param fluid fluid to lock to; if null the call is a no-op and returns true + * @return true if the lock was acquired or already held for the same fluid + */ + public boolean tryLock(BlockPos pos, Fluid fluid) { + if (fluid == null) return true; + boolean ok = locks.compute(pos, (k,v) -> v == null ? fluid : v) == fluid; + if (ok) setDirty(); + return ok; + } + + /** + * Check whether the given fluid is acceptable for the controller at {@code pos}. + * @param pos controller position + * @param fluid fluid to check + * @return true if no lock is present or the lock matches the provided fluid + */ + public boolean canAccept(BlockPos pos, Fluid fluid) { + if (fluid == null) return true; + Fluid locked = locks.get(pos); + return locked == null || locked == fluid; + } + + /** + * Clear any persistent lock for the specified controller position. + * Marks the saved data as dirty when a lock was removed. + */ + public void clearLock(BlockPos pos) { + if (locks.remove(pos) != null) setDirty(); + } + + public void readFrom(CompoundTag nbt) { + locks.clear(); + ListTag list = nbt.getList("locks", 10); + list.forEach(tag -> { + CompoundTag e = (CompoundTag) tag; + BlockPos pos = new BlockPos(e.getInt("x"), e.getInt("y"), e.getInt("z")); + ResourceLocation rl = ResourceLocation.tryParse(e.getString("fluid")); + if (rl != null) { + Fluid f = BuiltInRegistries.FLUID.get(rl); + if (f != null) locks.put(pos, f); + } + }); + } + + @Override + public @NotNull CompoundTag save(@NotNull CompoundTag nbt, @NotNull HolderLookup.Provider registries) { + ListTag list = new ListTag(); + locks.forEach((pos, fluid) -> { + CompoundTag e = new CompoundTag(); + e.putInt("x", pos.getX()); + e.putInt("y", pos.getY()); + e.putInt("z", pos.getZ()); + ResourceLocation rl = BuiltInRegistries.FLUID.getKey(fluid); + if (rl != null) { + e.putString("fluid", rl.toString()); + } + list.add(e); + }); + nbt.put("locks", list); + return nbt; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/PlayerInteractReactorFluidInput.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/PlayerInteractReactorFluidInput.java new file mode 100644 index 0000000..ca1db27 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/PlayerInteractReactorFluidInput.java @@ -0,0 +1,112 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.fluid; + +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import com.simibubi.create.content.fluids.transfer.GenericItemFilling; +import com.simibubi.create.foundation.fluid.FluidHelper; +import com.simibubi.create.foundation.fluid.FluidHelper.FluidExchange; +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; + +public class PlayerInteractReactorFluidInput { + public static InteractionResult interact(Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, boolean onClient, BlockHitResult ray) { + FluidExchange exchange = null; + ReactorFluidInputEntity be = (ReactorFluidInputEntity) level.getBlockEntity(pos); + if (be == null) { + return InteractionResult.FAIL; + } + + IFluidHandler fluidInput = level.getCapability(Capabilities.FluidHandler.BLOCK, pos, null); + if (fluidInput == null) return InteractionResult.PASS; + + FluidStack prevFluidInInput = fluidInput.getFluidInTank(0).copy(); + + if (FluidHelper.tryEmptyItemIntoBE(level, player, hand, stack, be)) exchange = FluidExchange.ITEM_TO_TANK; + if (FluidHelper.tryFillItemFromBE(level, player, hand, stack, be)) exchange = FluidExchange.TANK_TO_ITEM; + + if (exchange == null) { + if (GenericItemEmptying.canItemBeEmptied(level, stack) || GenericItemFilling.canItemBeFilled(level, stack)) return InteractionResult.SUCCESS; + return InteractionResult.PASS; + } + + SoundEvent soundEvent = null; + BlockState fluidState = null; + FluidStack fluidInInput = fluidInput.getFluidInTank(0); + + if (exchange == FluidExchange.ITEM_TO_TANK) { + if (player.isCreative() && !onClient) { + FluidStack fluidInItem = GenericItemEmptying.emptyItem(level, stack, true).getFirst(); +// if (!fluidInItem.isEmpty() && fluidInInput instanceof ReactorLiquidInput) { +// fluidInInput.set +// } + } + + Fluid fluid = fluidInInput.getFluid(); + fluidState = fluid.defaultFluidState().createLegacyBlock(); + soundEvent = FluidHelper.getEmptySound(fluidInInput); + } + + if (exchange == FluidExchange.TANK_TO_ITEM) { + if ( player.isCreative() && !onClient) { + + } + + Fluid fluid = prevFluidInInput.getFluid(); + fluidState = fluid.defaultFluidState().createLegacyBlock(); + soundEvent = FluidHelper.getFillSound(prevFluidInInput); + } + + if (soundEvent != null && !onClient) { + float pitch = Mth + .clamp(1 - (1f * fluidInInput.getAmount() / (FluidTankBlockEntity.getCapacityMultiplier() * 16)), 0, 1); + pitch /= 1.5f; + pitch += .5f; + pitch += (level.random.nextFloat() - .5f) / 4f; + level.playSound(null, pos, soundEvent, SoundSource.BLOCKS, .5f, pitch); + } + + if (!FluidStack.isSameFluidSameComponents(fluidInInput, prevFluidInInput) || fluidInInput.getAmount() != prevFluidInInput.getAmount()) { + if (be instanceof ReactorFluidInputEntity) { + if (fluidState != null && onClient) { + BlockParticleOption blockParticleData = + new BlockParticleOption(ParticleTypes.BLOCK, fluidState); + float flevel = (float) fluidInInput.getAmount() / fluidInput.getTankCapacity(0); + + boolean reversed = fluidInInput.getFluid() + .getFluidType() + .isLighterThanAir(); + if (reversed) + flevel = 1 - flevel; + + Vec3 vec = ray.getLocation(); + vec = new Vec3(vec.x, be.getBlockPos() + .getY() + flevel * (1 - .5f) + .25f, vec.z); + Vec3 motion = player.position() + .subtract(vec) + .scale(1 / 20f); + vec = vec.add(motion); + level.addParticle(blockParticleData, vec.x, vec.y, vec.z, motion.x, motion.y, motion.z); + return InteractionResult.SUCCESS; + } + } + } + return InteractionResult.SUCCESS; + + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/ReactorFluidInput.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/ReactorFluidInput.java new file mode 100644 index 0000000..d70af53 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/ReactorFluidInput.java @@ -0,0 +1,121 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.fluid; + +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.nuclearteam.createnuclear.CNBlockEntityTypes; +import net.nuclearteam.createnuclear.CNShapes; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancementBehaviour; +import net.nuclearteam.createnuclear.foundation.block.MultiDirectionalReactorBlock; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; + +public class ReactorFluidInput extends MultiDirectionalReactorBlock implements IWrenchable, IBE { + + public ReactorFluidInput(Properties properties) { + super(properties); + } + + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean moved) { + super.onPlace(state, world, pos, oldState, moved); + MultiblockHelpers.handleOnPlace(pos, world, ReactorControllerBlockEntity::addInputFluid); + } + + @Override + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity pPlacer, ItemStack stack) { + super.setPlacedBy(level, pos, state, pPlacer, stack); + CNAdvancementBehaviour.setPlacedBy(level, pos, pPlacer); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(FACING); + super.createBlockStateDefinition(builder); + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + return InteractionResult.SUCCESS; + } + + @Override + public VoxelShape getBlockSupportShape(BlockState pState, BlockGetter pReader, BlockPos pPos) { + return Shapes.block(); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return this.defaultBlockState() + .setValue(FACING, context.getNearestLookingDirection().getOpposite()); + } + + @Override + public @NotNull VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return CNShapes.REACTOR_FLUID_INPUT.get(state.getValue(FACING)); + } + + @Override + protected @NotNull ItemInteractionResult useItemOn(ItemStack heldItem, BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult ray) { + boolean onClient = world.isClientSide; + + if (heldItem.isEmpty()) + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + if (!player.isCreative()) + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + + InteractionResult result = PlayerInteractReactorFluidInput.interact(world, pos, player, hand, heldItem, onClient, ray); + + // Convertit le vieux InteractionResult en ItemInteractionResult si nécessaire pour NeoForge + return result.consumesAction() ? ItemInteractionResult.SUCCESS : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + } + + @Override + public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { + super.playerDestroy(level, player, pos, state, blockEntity, tool); + MultiblockHelpers.handleRemoval(pos, level, ReactorControllerBlockEntity::removeInputFluid); + } + + @Override + public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { + super.onRemove(state, world, pos, newState, isMoving); + MultiblockHelpers.handleRemoval(pos, world, ReactorControllerBlockEntity::removeInputFluid); + } + + @Override + public Class getBlockEntityClass() { + return ReactorFluidInputEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return CNBlockEntityTypes.REACTOR_FLUID_INPUT.get(); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState state) { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/ReactorFluidInputEntity.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/ReactorFluidInputEntity.java new file mode 100644 index 0000000..462d6c0 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/ReactorFluidInputEntity.java @@ -0,0 +1,229 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.fluid; + +import com.simibubi.create.api.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.fluid.SmartFluidTank; +import net.createmod.catnip.animation.LerpedFloat; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; +import net.nuclearteam.createnuclear.CNBlockEntityTypes; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.fluids.capability.templates.FluidTank; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class ReactorFluidInputEntity extends SmartBlockEntity implements IHaveGoggleInformation { + + /** Capacité par défaut tant que l'input n'est rattaché à aucun réacteur assemblé. */ + public static final int DEFAULT_CAPACITY = 16000; + + private final FluidTank internalTank; + private final IFluidHandler capabilityHandler; + private LerpedFloat fluidLevel; + + public ReactorFluidInputEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + internalTank = new SmartFluidTank(DEFAULT_CAPACITY, this::onTankContentsChanged); + capabilityHandler = new FilteredFluidHandler(); + } + + public IFluidHandler getCapabilityHandler() { + return capabilityHandler; + } + + public static void registerCapabilities(RegisterCapabilitiesEvent event) { + event.registerBlockEntity( + Capabilities.FluidHandler.BLOCK, + CNBlockEntityTypes.REACTOR_FLUID_INPUT.get(), + (be, context) -> be.capabilityHandler + ); + } + + /** + * Capacité du tank en fonction de la taille du réacteur (tier). + * 5x5 -> tier 1, 7x7 -> tier 2, 9x9 -> tier 3. + */ + public static int getCapacityForReactorSize(int reactorSize) { + return switch (reactorSize) { + case 5 -> 144000; + case 7 -> 448000; + case 9 -> 848000; + default -> DEFAULT_CAPACITY; + }; + } + + /** + * Applies an explicit tank capacity to this input. + *

+ * The per-reactor-size capacity ({@link #getCapacityForReactorSize(int)}) is the TOTAL the + * reactor should hold, split across all fluid inputs by {@code ReactorAssembler}, so the sum + * of every input's capacity stays equal to the configured value no matter how many inputs the + * player places. + */ + public void applyCapacity(int capacity) { + if (internalTank.getCapacity() == capacity) return; + internalTank.setCapacity(capacity); + if (level != null && !level.isClientSide) { + setChanged(); + sendData(); + } + } + + @Override + public void addBehaviours(List behaviours) { + } + + @Override + protected void write(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) { + super.write(tag, registries, clientPacket); + CompoundTag tankTag = internalTank.writeToNBT(registries, new CompoundTag()); // Pensez à passer registries si requis par la v1.20+ pour les tanks, ou conservez new CompoundTag() selon votre version + tag.put("tank", tankTag); + tag.putInt("capacity", internalTank.getCapacity()); + } + + @Override + protected void read(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) { + super.read(tag, registries, clientPacket); + if (tag.contains("capacity")) + internalTank.setCapacity(tag.getInt("capacity")); + internalTank.readFromNBT(registries, tag.getCompound("tank")); // Pareil ici selon l'implémentation de SmartFluidTank + + if (tag.contains("ForceFluidLevel") || fluidLevel == null) + fluidLevel = LerpedFloat.linear() + .startWithValue(getFillState()); + } + + public float getFillState() { + return (float) internalTank.getFluidAmount() / internalTank.getCapacity(); + } + + protected void onTankContentsChanged(FluidStack contents) { + // Avoid accessing level during deserialization when the block entity isn't attached yet + if (this.level == null) { + if (fluidLevel == null) + fluidLevel = LerpedFloat.linear() + .startWithValue(getFillState()); + return; + } + + if (!level.isClientSide) { + setChanged(); + sendData(); + } + + if (isVirtual()) { + if (fluidLevel == null) + fluidLevel = LerpedFloat.linear() + .startWithValue(getFillState()); + fluidLevel.chase(getFillState(), .5f, LerpedFloat.Chaser.EXP); + } + + if (!level.isClientSide && internalTank.getFluidAmount() == 0) { + ReactorControllerBlockEntity controller = MultiblockHelpers.getControllerForPart(level, worldPosition); + if (controller != null) controller.clearLockIfAllInputsEmpty(); + } + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + return containedFluidTooltip(tooltip, isPlayerSneaking, internalTank); + } + + private class FilteredFluidHandler implements IFluidHandler { + private final IFluidHandler delegate = internalTank; + + @Override + public int getTanks() { + return delegate.getTanks(); + } + + @Override + public @NotNull FluidStack getFluidInTank(int tank) { + return delegate.getFluidInTank(tank); + } + + @Override + public int getTankCapacity(int tank) { + return delegate.getTankCapacity(tank); + } + + @Override + public boolean isFluidValid(int tank, @NotNull FluidStack stack) { + return delegate.isFluidValid(tank, stack); + } + + @Override + public int fill(FluidStack resource, FluidAction action) { + if (resource == null || resource.isEmpty()) return 0; + ReactorControllerBlockEntity controller = MultiblockHelpers.getControllerForPart(level, worldPosition); + BlockPos controllerPos = controller != null ? controller.getBlockPos() : null; + + if (controllerPos != null && level instanceof ServerLevel serverLevel) { + PersistentFluidLocks lock = PersistentFluidLocks.get(serverLevel); + if (!lock.canAccept(controllerPos, resource.getFluid())) return 0; + } else if (controllerPos != null) { + if (!FluidLockManager.canAccept(controllerPos, resource)) return 0; + } + + int filled = delegate.fill(resource, action); + if (filled > 0 && action.execute() && controllerPos != null ){ + if (level instanceof ServerLevel serverLevel) { + PersistentFluidLocks.get(serverLevel).tryLock(controllerPos, resource.getFluid()); + } else { + FluidLockManager.tryLock(controllerPos, resource.getFluid()); + } + } + return filled; + } + + @Override + public @NotNull FluidStack drain(FluidStack resource, FluidAction action) { + FluidStack drained = delegate.drain(resource, action); + if (!drained.isEmpty() && action.execute()) { + ReactorControllerBlockEntity controller = MultiblockHelpers.getControllerForPart(level, worldPosition); + if (controller != null) { + BlockPos controllerPos = controller.getBlockPos(); + if (delegate.getFluidInTank(0).isEmpty()) { + if (level instanceof ServerLevel serverLevel) { + PersistentFluidLocks.get(serverLevel).clearLock(controllerPos); + } else { + FluidLockManager.clearLock(controllerPos); + } + } + } + } + return drained; + } + + @Override + public @NotNull FluidStack drain(int maxDrain, FluidAction action) { + FluidStack drained = delegate.drain(maxDrain, action); + if (!drained.isEmpty() && action.execute()) { + ReactorControllerBlockEntity controller = MultiblockHelpers.getControllerForPart(level, worldPosition); + if (controller != null) { + BlockPos controllerPos = controller.getBlockPos(); + if (delegate.getFluidInTank(0).isEmpty()) { + if (level instanceof ServerLevel serverLevel) { + PersistentFluidLocks.get(serverLevel).clearLock(controllerPos); + } else { + FluidLockManager.clearLock(controllerPos); + } + } + } + } + return drained; + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/ReactorFluidInputGenerator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/ReactorFluidInputGenerator.java new file mode 100644 index 0000000..e80c5fd --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/ReactorFluidInputGenerator.java @@ -0,0 +1,34 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.fluid; + +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.client.model.generators.ModelFile; + +public class ReactorFluidInputGenerator extends SpecialBlockStateGen { + @Override + protected int getXRotation(BlockState state) { + return state.getValue(ReactorFluidInput.FACING) == Direction.DOWN ? 180 : 0; + } + + @Override + protected int getYRotation(BlockState state) { + return state.getValue(ReactorFluidInput.FACING).getAxis().isVertical() + ? 0 + : horizontalAngle(state.getValue(ReactorFluidInput.FACING)); + } + + @Override + public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { + return prov + .models() + .getExistingFile(prov + .modLoc("block/reactor/fluid_input/fluid_input" + (state.getValue(ReactorFluidInput.FACING).getAxis().isVertical() + ? "_vertical" + : "" + ))); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/VirtualReactorInputFluid.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/VirtualReactorInputFluid.java new file mode 100644 index 0000000..aea43a8 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/fluid/VirtualReactorInputFluid.java @@ -0,0 +1,92 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.fluid; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.material.Fluid; +import net.neoforged.neoforge.fluids.FluidStack; +import net.minecraft.core.registries.BuiltInRegistries; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * A lightweight, in-memory aggregation of fluid quantities keyed by + * fluid ResourceLocation. This record is used to represent the combined + * input fluids available to a reactor without modifying the real handlers. + */ +public record VirtualReactorInputFluid(Map fluids) { + + /** + * Create an empty virtual inventory. + */ + public VirtualReactorInputFluid() { + this(new HashMap<>()); + } + + /** + * Add the contents of the provided FluidStack to this virtual inventory. + * Empty stacks or non-registered fluids are ignored. + * @param stack the fluid stack to add + */ + public void addFluid(@NotNull FluidStack stack) { + if (stack.isEmpty() || stack.getAmount() <= 0) return; + ResourceLocation id = BuiltInRegistries.FLUID.getKey(stack.getFluid()); + if (id == null) return; + fluids.merge(id, (long) stack.getAmount(), Long::sum); + } + + /** + * Remove up to {@code amount} units of the specified fluid from this virtual inventory. + * Returns a FluidStack describing the removed amount (or {@link FluidStack#EMPTY}). + * @param fluidId fluid identifier + * @param amount maximum amount to remove + */ + public FluidStack removeFluid(@NotNull ResourceLocation fluidId, long amount) { + if (amount < 0 || fluidId == null) return FluidStack.EMPTY; + long current = fluids.getOrDefault(fluidId, 0L); + long removed = Math.min(current, amount); + if (removed == 0) return FluidStack.EMPTY; + long remaining = current - removed; + if (remaining == 0) fluids.remove(fluidId); + else fluids.put(fluidId, remaining); + + int removedInt = (int) Math.min(removed, Integer.MAX_VALUE); + return new FluidStack(BuiltInRegistries.FLUID.get(fluidId), removedInt); + } + + /** + * Get the stored amount for the given fluid id. + * @param fluidId fluid identifier + * @return total amount stored for that fluid + */ + public long getAmount(@NotNull ResourceLocation fluidId) { + if (fluidId == null) return 0L; + return fluids.getOrDefault(fluidId, 0L); + } + + /** + * Convert a map of ResourceLocation->long into a list of BigFluidStack + * suitable for display or consumption elsewhere. + */ + public static List toBigList(Map map) { + List list = new ArrayList<>(); + for (Entry e : map.entrySet()) { + ResourceLocation id = e.getKey(); + long total = e.getValue(); + Fluid fluid = BuiltInRegistries.FLUID.get(id); + if (fluid == null || total <= 0) continue; + int amount = (int) Math.min(total, BigFluidStack.INF); + list.add(new BigFluidStack(new FluidStack(fluid, amount), amount)); + } + return list; + } + + @Override + public @NotNull String toString() { + return "VirtualReactorInputFluid" + fluids.toString(); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInput.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInput.java new file mode 100644 index 0000000..50a297d --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInput.java @@ -0,0 +1,110 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.item; + +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.item.ItemHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.ItemInteractionResult; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; + +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +import net.nuclearteam.createnuclear.CNBlockEntityTypes; +import net.nuclearteam.createnuclear.CNShapes; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.foundation.block.MultiDirectionalReactorBlock; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + + +@ParametersAreNonnullByDefault +public class ReactorRodInput extends MultiDirectionalReactorBlock implements IWrenchable, IBE { + + public ReactorRodInput(Properties properties) { + super(properties); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(FACING); + super.createBlockStateDefinition(builder); + } + + @Override + public ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { + ItemStack itemInHand = player.getItemInHand(hand); + + if (itemInHand.getItem() instanceof BlockItem) { + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + } + + + if (level.isClientSide()) {return ItemInteractionResult.SUCCESS;} + + withBlockEntityDo(level, pos, be -> player.openMenu(be, be::sendToMenu)); + return ItemInteractionResult.SUCCESS; + } + + @Override + public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, level, pos, oldState, isMoving); + MultiblockHelpers.handleOnPlace(pos, level, ReactorControllerBlockEntity::addInput); + } + + @Override + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity pPlacer, ItemStack stack) { + super.setPlacedBy(level, pos, state, pPlacer, stack); + MultiblockHelpers.handleAdvancedPlacedBy(pos, level, pPlacer); + } + + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + // Only act when the block is actually removed/replaced, not on a mere state change + // (e.g. a FACING update) — otherwise rotating the block would spill its rods. + if (!pState.is(pNewState.getBlock())) { + // Drop the contents BEFORE super removes the block entity: super.onRemove() + // calls level.removeBlockEntity(pos), after which the inventory is gone. + withBlockEntityDo(pLevel, pPos, be -> ItemHelper.dropContents(pLevel, pPos, be.inventory)); + MultiblockHelpers.handleRemoval(pPos, pLevel, ReactorControllerBlockEntity::removeInput); + } + super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return this.defaultBlockState() + .setValue(FACING, context.getNearestLookingDirection().getOpposite()); + } + @Override + public @NotNull VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return CNShapes.REACTOR_INPUT.get(state.getValue(FACING)); + } + + @Override + public Class getBlockEntityClass() { + return ReactorRodInputEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return CNBlockEntityTypes.REACTOR_INPUT.get(); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputEntity.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputEntity.java new file mode 100644 index 0000000..b7819c8 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputEntity.java @@ -0,0 +1,96 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.item; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; +import net.nuclearteam.createnuclear.CNBlockEntityTypes; + +import javax.annotation.Nullable; +import java.util.List; + +public class ReactorRodInputEntity extends SmartBlockEntity implements MenuProvider { + protected BlockPos block; + + public ReactorRodInputInventory inventory; + + + public ReactorRodInputEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + inventory = new ReactorRodInputInventory(this); + } + + public static void registerCapabilities(RegisterCapabilitiesEvent event) { + event.registerBlockEntity( + Capabilities.ItemHandler.BLOCK, + CNBlockEntityTypes.REACTOR_INPUT.get(), + (be, context) -> be.inventory + ); + } + + @Override + public void addBehaviours(List behaviours) { } + + @Override + protected void read(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) { + if (!clientPacket) { + inventory.deserializeNBT(registries, tag.getCompound("Inventory")); + } + super.read(tag, registries, clientPacket); + } + + @Override + protected void write(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) { + if (!clientPacket) { + tag.put("Inventory", inventory.serializeNBT(registries)); + } + super.write(tag, registries, clientPacket); + } + + + @Nullable + @Override + public Level getLevel() { + return super.getLevel(); + } + + + @Override + public Component getDisplayName() { + return Component.translatable("gui.createnuclear.reactor_input.title"); + } + + @Nullable + @Override + public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { + return ReactorRodInputMenu.create(i, inventory, this); + } + + @Override + public void tick() { + super.tick(); + } + + + /*protected boolean isItemHandlerCap(Capability cap) { + return cap == ForgeCapabilities.ITEM_HANDLER; + }*/ + + /*@Override + public ResetableLazy getCapability(Capability cap, Direction side) { + if (isItemHandlerCap(cap)) + return inventoryProvider.cast(); + return super.getCapability(cap, side); + }*/ +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputGenerator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputGenerator.java new file mode 100644 index 0000000..b038c38 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputGenerator.java @@ -0,0 +1,34 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.item; + +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.client.model.generators.ModelFile; + +public class ReactorRodInputGenerator extends SpecialBlockStateGen { + @Override + protected int getXRotation(BlockState state) { + return state.getValue(ReactorRodInput.FACING) == Direction.DOWN ? 180 : 0; + } + + @Override + protected int getYRotation(BlockState state) { + return state.getValue(ReactorRodInput.FACING).getAxis().isVertical() + ? 0 + : horizontalAngle(state.getValue(ReactorRodInput.FACING)); + } + + @Override + public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, BlockState state) { + return prov + .models() + .getExistingFile(prov + .modLoc("block/reactor/rod_input/rod_input" + (state.getValue(ReactorRodInput.FACING).getAxis().isVertical() + ? "_vertical" + : "" + ))); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputInventory.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputInventory.java new file mode 100644 index 0000000..117abfb --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputInventory.java @@ -0,0 +1,32 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.item; + + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.items.ItemStackHandler; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType.TypeRodPredicate; +import org.jetbrains.annotations.NotNull; + +public class ReactorRodInputInventory extends ItemStackHandler { + private final ReactorRodInputEntity be; + + public ReactorRodInputInventory(ReactorRodInputEntity be) { + super(1); + this.be = be; + } + + @Override + protected void onContentsChanged(int slot) { + super.onContentsChanged(slot); + be.setChanged(); + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + Level level = be.getLevel(); + return switch (slot) { + case 0 -> level != null && (TypeRodPredicate.isFuel(stack, level) || TypeRodPredicate.isCooled(stack, level)); + default -> !super.isItemValid(slot, stack); + }; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputMenu.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputMenu.java new file mode 100644 index 0000000..b40d581 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputMenu.java @@ -0,0 +1,126 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.item; + +import com.simibubi.create.foundation.gui.menu.MenuBase; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.neoforged.neoforge.items.SlotItemHandler; +import net.nuclearteam.createnuclear.CNMenus; + +public class ReactorRodInputMenu extends MenuBase { + + + public ReactorRodInputMenu(MenuType type, int id, Inventory inv, RegistryFriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public ReactorRodInputMenu(MenuType type, int id, Inventory inv, ReactorRodInputEntity contentHolder) { + super(type, id, inv, contentHolder); + } + + public static ReactorRodInputMenu create(int id, Inventory inv, ReactorRodInputEntity contentHolder) { + return new ReactorRodInputMenu(CNMenus.SLOT_ITEM_STORAGE.get(), id, inv, contentHolder); + } + + @Override + public ItemStack quickMoveStack(Player playerIn, int index) { + ItemStack result = ItemStack.EMPTY; + Slot slot = this.slots.get(index); + if (slot != null && slot.hasItem()) { + ItemStack stackInSlot = slot.getItem(); + result = stackInSlot.copy(); + + int playerInventorySize = player.getInventory().items.size(); // normally 36 + int containerStart = playerInventorySize; + int containerEnd = containerStart + 1; // 1 machine slot + + // Clicked a machine slot (after the player slots) + if (index >= containerStart && index < containerEnd) { + if (!this.moveItemStackTo(stackInSlot, 0, playerInventorySize, true)) { + return ItemStack.EMPTY; + } + } else { + // Clicked a player slot — try moving the stack into the machine container + if (!this.moveItemStackTo(stackInSlot, containerStart, containerEnd, false)) { + return ItemStack.EMPTY; + } + } + + if (stackInSlot.isEmpty()) { + slot.set(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + + if (stackInSlot.getCount() == result.getCount()) { + return ItemStack.EMPTY; + } + + slot.onTake(playerIn, stackInSlot); + } + return result; + } + + + + @Override + protected ReactorRodInputEntity createOnClient(RegistryFriendlyByteBuf extraData) { + ClientLevel world = Minecraft.getInstance().level; + BlockEntity blockEntity = world.getBlockEntity(extraData.readBlockPos()); + + if (blockEntity instanceof ReactorRodInputEntity reactorInput) { + reactorInput.readClient(extraData.readNbt(), extraData.registryAccess()); + return reactorInput; + } + return null; + } + + @Override + protected void initAndReadInventory(ReactorRodInputEntity contentHolder) { + + } + + @Override + protected void addSlots() { + // player Slots + for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) { + this.addSlot(new Slot(player.getInventory(), hotbarSlot, -31 + hotbarSlot * 18, 155)); + } + + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 9; ++col) { + this.addSlot(new Slot(player.getInventory(), col + row * 9 + 9, -31 + col * 18, 97 + row * 18)); + } + } + + Slot slot1 = new SlotItemHandler(contentHolder.inventory, 0, 42, 29); + + addSlot(slot1); + } + + @Override + protected void saveData(ReactorRodInputEntity contentHolder) { + } + + @Override + public void clicked(int slotId, int button, ClickType clickType, Player player) { + if (clickType == ClickType.THROW) { + int[] targetSlotIds = {9, 18, 27, 0, 1, 28, 19, 10, 16, 17, 26, 25, 34, 35, 8, 7}; + for (int id : targetSlotIds) { + if (slotId == id) { + clickType = ClickType.PICKUP; + super.clicked(slotId, button, clickType, player); + } + } + return; + } + super.clicked(slotId, button, clickType, player); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputScreen.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputScreen.java new file mode 100644 index 0000000..5b6621d --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/ReactorRodInputScreen.java @@ -0,0 +1,39 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.item; + +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; +import net.nuclearteam.createnuclear.foundation.gui.CNGuiTextures; + +import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; + +public class ReactorRodInputScreen extends AbstractSimiContainerScreen { + + protected static final CNGuiTextures background = CNGuiTextures.REACTOR_SLOT_INVENTOR; + + public ReactorRodInputScreen(ReactorRodInputMenu container, Inventory inv, Component title) { + super(container, inv, title); + } + + @Override + protected void init() { + setWindowSize(background.width, background.height+ 4 + AllGuiTextures.PLAYER_INVENTORY.getHeight()); + setWindowOffset(0,0); + super.init(); + } + + @Override + protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) { + int invX = getLeftOfCentered(PLAYER_INVENTORY.getWidth()); + int invY = topPos + background.height + 4; + renderPlayerInventory(guiGraphics, invX, invY); + + int x = leftPos; + int y = topPos; + + background.render(guiGraphics, x, y); + + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/VirtualReactorInputsItem.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/VirtualReactorInputsItem.java new file mode 100644 index 0000000..5964ff3 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/input/item/VirtualReactorInputsItem.java @@ -0,0 +1,25 @@ +package net.nuclearteam.createnuclear.content.multiblock.input.item; + +import com.simibubi.create.content.logistics.BigItemStack; +import net.nuclearteam.createnuclear.CNItems; +import org.jetbrains.annotations.NotNull; + +public record VirtualReactorInputsItem(int fuel, int cooler) { + public VirtualReactorInputsItem() { + this(0,0); + } + + public BigItemStack getBigFuelRod() { + return new BigItemStack(CNItems.URANIUM_ROD.asStack(), fuel); + } + + public BigItemStack getBigCooledRod() { + return new BigItemStack(CNItems.GRAPHITE_ROD.asStack(), cooler); + } + + @Override + public @NotNull String toString() { + return "fuel: " + fuel + " cooler: " + cooler; + } +} + diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/output/ReactorOutput.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/output/ReactorOutput.java index 7ed93a4..f56e114 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/output/ReactorOutput.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/output/ReactorOutput.java @@ -1,25 +1,29 @@ package net.nuclearteam.createnuclear.content.multiblock.output; +import com.simibubi.create.AllBlocks; import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; import com.simibubi.create.foundation.block.IBE; +import net.createmod.catnip.placement.IPlacementHelper; +import net.createmod.catnip.placement.PlacementHelpers; +import net.createmod.catnip.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Vec3i; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; @@ -29,76 +33,50 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import net.nuclearteam.createnuclear.*; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.List; -import java.util.Objects; +import java.util.function.Predicate; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class ReactorOutput extends DirectionalKineticBlock implements IWrenchable, IBE { - - //public static final IntegerProperty SPEED = IntegerProperty.create("speed", 0, 256); public static final IntegerProperty DIR = IntegerProperty.create("dir", 0, 2); + private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); + public ReactorOutput(Properties properties) { super(properties); } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { - //builder.add(SPEED); builder.add(DIR); super.createBlockStateDefinition(builder); } - @Override - public ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { - if (level.isClientSide) - return ItemInteractionResult.SUCCESS; - else { - ReactorControllerBlock controller = FindController(pos, level, level.players(), false); - if (controller != null){ - ReactorControllerBlockEntity entity = controller.getBlockEntity(level, pos.above(3)); - assert entity != null; - if (entity.getAssembled()){ - ReactorOutputEntity control = Objects.requireNonNull(getBlockEntity(level, pos)); - if (control.getDir() == 0) - control.setDir(1, level, pos); - else control.setDir(0, level, pos); - } - } - return ItemInteractionResult.CONSUME; - } - } @Override public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { super.onPlace(state, level, pos, oldState, isMoving); - List players = level.players(); - FindController(pos, level, players, true); + MultiblockHelpers.handleOnPlace(pos, level, ReactorControllerBlockEntity::addOutput); } @Override - public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { - super.playerDestroy(level, player, pos, state, blockEntity, tool); - List players = level.players(); - FindController(pos, level, players, false); + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @javax.annotation.Nullable LivingEntity pPlacer, ItemStack stack) { + super.setPlacedBy(level, pos, state, pPlacer, stack); + MultiblockHelpers.handleAdvancedPlacedBy(pos, level, pPlacer); } @Override public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving); - List players = pLevel.players(); - FindController(pPos, pLevel, players, false); + MultiblockHelpers.handleRemoval(pPos, pLevel, ReactorControllerBlockEntity::removeOutput); } @Override - public @NotNull VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { return CNShapes.REACTOR_OUTPUT.get(state.getValue(FACING)); } @@ -108,7 +86,21 @@ public BlockState getStateForPlacement(BlockPlaceContext context) { if ((context.getPlayer() != null && context.getPlayer() .isShiftKeyDown()) || preferred == null) return super.getStateForPlacement(context); - return defaultBlockState().setValue(FACING, preferred)/*.setValue(SPEED, 0)*/.setValue(DIR, 0); + return defaultBlockState().setValue(FACING, preferred).setValue(DIR, 0); + } + + @Override + public ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { + ItemStack heldItem = player.getItemInHand(hand); + IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); + if (!player.isShiftKeyDown() && player.mayBuild()) { + if (placementHelper.matchesItem(heldItem) && placementHelper.getOffset(player, level, state, pos, hitResult) + .placeInWorld(level, (BlockItem) heldItem.getItem(), player, hand, hitResult) + .consumesAction()) + return ItemInteractionResult.SUCCESS; + } + + return super.useItemOn(stack, state, level, pos, player, hand, hitResult); } // IRotate: @@ -129,6 +121,11 @@ public boolean hideStressImpact() { return true; } + @Override + public boolean isPathfindable(BlockState state, PathComputationType type) { + return false; + } + @Override public Class getBlockEntityClass() { return ReactorOutputEntity.class; @@ -139,18 +136,27 @@ public BlockEntityType getBlockEntityType() { return CNBlockEntityTypes.REACTOR_OUTPUT.get(); } - public ReactorControllerBlock FindController(BlockPos blockPos, Level level, List players, boolean first) { - BlockPos newBlock; // to find the controller and verify the pattern - Vec3i pos = new Vec3i(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - newBlock = new BlockPos(pos.getX(), pos.getY() + 3, pos.getZ()); - if (level.getBlockState(newBlock).is(CNBlocks.REACTOR_CONTROLLER.get())) { // verifying the pattern - ReactorControllerBlock controller = (ReactorControllerBlock) level.getBlockState(newBlock).getBlock(); - controller.Verify(level.getBlockState(newBlock), newBlock, level, players, first); - ReactorControllerBlockEntity entity = controller.getBlockEntity(level, newBlock); - if (entity.created) { - return controller; - } + private static class PlacementHelper implements IPlacementHelper { + + @Override + public Predicate getItemPredicate() { + return AllBlocks.SHAFT::isIn; + } + + @Override + public Predicate getStatePredicate() { + return s -> s.getBlock() instanceof ReactorOutput; + } + + @Override + public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, BlockHitResult ray) { + Direction facing = state.getValue(FACING); + BlockPos target = pos.relative(facing); + + if (!world.getBlockState(target).canBeReplaced()) + return PlacementOffset.fail(); + + return PlacementOffset.success(target, s -> s.setValue(BlockStateProperties.AXIS, facing.getAxis())); } - return null; } -} \ No newline at end of file +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/output/ReactorOutputEntity.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/output/ReactorOutputEntity.java index 8e0a4c3..565e70f 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/output/ReactorOutputEntity.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/output/ReactorOutputEntity.java @@ -2,151 +2,143 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; -import com.simibubi.create.content.kinetics.motor.KineticScrollValueBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; import com.simibubi.create.foundation.utility.CreateLang; import dev.engine_room.flywheel.lib.transform.TransformStack; import net.createmod.catnip.math.AngleHelper; +import net.createmod.catnip.math.VecHelper; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; -import net.nuclearteam.createnuclear.CNBlocks; +import net.minecraft.util.Mth; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; -import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; +import net.nuclearteam.createnuclear.content.multiblock.pattern.ReactorPattern; import java.util.List; -import java.util.Objects; - -import static net.nuclearteam.createnuclear.content.multiblock.output.ReactorOutput.DIR; - public class ReactorOutputEntity extends GeneratingKineticBlockEntity { - public int speed = 1; + public int speed = 0; public float heat = 0; - ReactorControllerBlock controller = null; - ReactorControllerBlockEntity controllerEntity = null; + protected ReactorPattern pattern = new ReactorPattern(); - protected ScrollValueBehaviour generatedSpeed; + protected float generatedSpeed; public ReactorOutputEntity(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); } - //KineticBlockEntity + @Override public void addBehaviours(List behaviours) { super.addBehaviours(behaviours); - generatedSpeed = new KineticScrollValueBehaviour(CreateNuclearLang.translateDirect("kinetics.reactor_output.rotation_speed"), this, new ReactorOutputValue()); - generatedSpeed.between(-1500000, 1500000); - generatedSpeed.setValue(speed); - generatedSpeed.withCallback(i -> this.updateGeneratedRotation()); - behaviours.add(generatedSpeed); - - } - @Override - public void tick() { - super.tick(); - - BlockGetter level = getLevel(); - - if (level.getBlockState(getBlockPos().above(3)).getBlock() == CNBlocks.REACTOR_CONTROLLER.get()) { - controller = (ReactorControllerBlock) level.getBlockState(getBlockPos().above(3)).getBlock(); - controllerEntity = (ReactorControllerBlockEntity) level.getBlockEntity(getBlockPos().above(3)); - if (controllerEntity != null) { - if (!controllerEntity.getAssembled() && getSpeed() != 0) { - setSpeed(0); - } - } - } else setSpeed(0); } @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + public void lazyTick() { + super.lazyTick(); - float stressBase = calculateAddedStressCapacity(); + determineSpeed(); + } - CreateLang.translate("gui.goggles.generator_stats") - .forGoggles(tooltip); - CreateLang.translate("tooltip.capacityProvided") - .style(ChatFormatting.GRAY) - .forGoggles(tooltip); + public void determineSpeed() { + int deterSpeed = this.speed; + setSpeedAndUpdate(deterSpeed); + } - float speed = getTheoreticalSpeed(); - speed = Math.abs(speed); + public void setSpeedAndUpdate(int speed) { + if (generatedSpeed == speed) return; - float stressTotal = stressBase * speed; + generatedSpeed = (float) speed; - CreateLang.number(stressTotal) - .translate("generic.unit.stress") - .style(ChatFormatting.AQUA) - .space() - .add(CreateLang.translate("gui.goggles.at_current_speed") - .style(ChatFormatting.DARK_GRAY)) - .forGoggles(tooltip, 1); - return true; + updateGeneratedRotation(); + setChanged(); } + // Tracks the output's linked block position for persistence across reloads. + private BlockPos outputPos; + @Override - public void initialize() { - super.initialize(); + protected void read(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) { + super.read(compound, registries, clientPacket); - if (!hasSource() || getGeneratedSpeed() > getTheoreticalSpeed()) - { - FindController(getBlockPos(), Objects.requireNonNull(getLevel())); + // Restore the generated rotation speed + generatedSpeed = compound.getFloat("generatedSpeed"); + + // Restore the output position, if present in the tag + if (compound.contains("outputPos")) { + this.outputPos = BlockPos.of(compound.getLong("outputPos")); } } - public void FindController(BlockPos pos, Level level){ - if (level.getBlockState(pos.above(3)).getBlock() == CNBlocks.REACTOR_CONTROLLER.get()){ - ReactorControllerBlock controller = (ReactorControllerBlock)level.getBlockState(pos.above(3)).getBlock(); - controller.Verify(controller.defaultBlockState(), pos.above(3), level, level.players(), false); + @Override + public void write(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) { + super.write(compound, registries, clientPacket); + + // Persist the generated rotation speed + compound.putFloat("generatedSpeed", generatedSpeed); + + // Persist the output position, if set + if (this.outputPos != null) { + compound.putLong("outputPos", this.outputPos.asLong()); } } - public void setSpeed(int speed) { - this.speed = speed; - } + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - public int getDir() { - BlockState state = getBlockState(); - return state.getValue(DIR); - } + float stressBase = calculateAddedStressCapacity(); - public void setDir(int dir, Level level, BlockPos pos) { - BlockState state = getBlockState(); - level.setBlockAndUpdate(pos, state.setValue(DIR, dir)); - } + CreateLang.translate("gui.goggles.generator_stats") + .forGoggles(tooltip); + CreateLang.translate("tooltip.capacityProvided") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + + float speed = getTheoreticalSpeed(); + speed = Math.abs(speed); + + float stressTotal = stressBase * speed; + + CreateLang.number(stressTotal) + .translate("generic.unit.stress") + .style(ChatFormatting.AQUA) + .space() + .add(CreateLang.translate("gui.goggles.at_current_speed") + .style(ChatFormatting.DARK_GRAY)) + .forGoggles(tooltip, 1); + return true; + } @Override - public float getGeneratedSpeed() { - if (!CNBlocks.REACTOR_OUTPUT.has(getBlockState())) - return 0; - return speed; //convertToDirection(speed, getBlockState().getValue(ReactorOutput.FACING)); + public void initialize() { + super.initialize(); + + if (!hasSource() || getGeneratedSpeed() > getTheoreticalSpeed()) + { + assert level != null; + pattern.findController(getBlockPos(), level, true); + } } @Override - protected Block getStressConfigKey() { - return super.getStressConfigKey(); + public float getGeneratedSpeed() { + return Mth.clamp(generatedSpeed, 0, 1500000); } - class ReactorOutputValue extends ValueBoxTransform.Sided { + static class ReactorOutputValue extends ValueBoxTransform.Sided { @Override protected Vec3 getSouthLocation() { - return net.createmod.catnip.math.VecHelper.voxelSpace(8, 8, 12.5); + return VecHelper.voxelSpace(8, 8, 12.5); } @Override @@ -177,4 +169,4 @@ protected boolean isSideActive(BlockState state, Direction direction) { } } -} \ No newline at end of file +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/pattern/ReactorPattern.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/pattern/ReactorPattern.java new file mode 100644 index 0000000..c776855 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/pattern/ReactorPattern.java @@ -0,0 +1,113 @@ +package net.nuclearteam.createnuclear.content.multiblock.pattern; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.pattern.BlockInWorld; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.content.multiblock.ReactorAssembler; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Predicate; + +public class ReactorPattern { + + private static final Predicate blockInWorldAPredicate = state -> + stateIs(CNBlocks.REACTOR_CASING.get()).test(state) + || stateIs(CNBlocks.REACTOR_OUTPUT.get()).test(state) + || stateIs(CNBlocks.REACTOR_ROD_INPUT.get()).test(state) + || stateIs(CNBlocks.REACTOR_FLUID_INPUT.get()).test(state) + || stateIs(CNBlocks.REACTOR_ALARM.get()).test(state) + ; + + private static Predicate stateIs(Block block) { + return a -> { + BlockState state = a.getState(); + return state != null && state.is(block); + }; + } + + @FunctionalInterface + private interface ControllerVisitor { + boolean visit(BlockPos controllerPos, ReactorControllerBlockEntity entity); + } + + private void scanControllerCandidates(BlockPos blockPos, Level level, ControllerVisitor visitor) { + BlockPos newBlock; + Vec3i pos = new Vec3i(blockPos.getX(), blockPos.getY(), blockPos.getZ()); + for (int y = pos.getY()-5; y != pos.getY()+6; y+=1) { + for (int x = pos.getX()-9; x != pos.getX()+10; x+=1) { + for (int z = pos.getZ()-9; z != pos.getZ()+10; z+=1) { + newBlock = new BlockPos(x, y, z); + if (level.getBlockState(newBlock).is(CNBlocks.REACTOR_CONTROLLER.get()) + && level.getBlockEntity(newBlock) instanceof ReactorControllerBlockEntity entity) { + if (visitor.visit(newBlock, entity)) { + return; + } + } + } + } + } + } + + public void findController(BlockPos blockPos, Level level, boolean first){ + scanControllerCandidates(blockPos, level, ((controllerPos, entity) -> { + boolean inRange = isInReactorRange(entity.getMultiblockPos(), blockPos); + if (first) { + if (inRange || !entity.isAssembled()) { + ReactorAssembler.assemble(controllerPos, level); + } + } else if (inRange) { + ReactorAssembler.disassemble(controllerPos, level); + } + + return false; + })); + } + + public BlockPos findControllerPos(BlockPos blockPos, Level level, boolean first){ + BlockPos[] found = {null}; + scanControllerCandidates(blockPos, level, ((controllerPos, entity) -> { + boolean inRange = isInReactorRange(entity.getMultiblockPos(), blockPos); + if (first) { + if (inRange || !entity.isAssembled()) { + ReactorAssembler.assemble(controllerPos, level); + } + } else if (inRange) { + ReactorAssembler.disassemble(controllerPos, level); + } + + if (isInReactorRange(entity.getMultiblockPos(), blockPos)) { + found[0] = controllerPos; + return true; + } + + return false; + })); + + return found[0]; + } + + public BlockPos findControllerPos(BlockPos blockPos, Level level){ + BlockPos[] found = {null}; + scanControllerCandidates(blockPos, level, ((controllerPos, entity) -> { + ReactorAssembler.assemble(controllerPos, level); + if (isInReactorRange(entity.getMultiblockPos(), blockPos)) { + found[0] = controllerPos; + return true; + } + + return false; + })); + + return found[0]; + } + + public boolean isInReactorRange(@Nullable BoundingBox reactorPos, BlockPos blockPos) { + return reactorPos != null && reactorPos.isInside(blockPos); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorCooler/ReactorCooler.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorCooler/ReactorCooler.java deleted file mode 100644 index 7ff6fc0..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorCooler/ReactorCooler.java +++ /dev/null @@ -1,66 +0,0 @@ -package net.nuclearteam.createnuclear.content.multiblock.reactorCooler; - -import com.simibubi.create.content.equipment.wrench.IWrenchable; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.nuclearteam.createnuclear.CNBlocks; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; - -import javax.annotation.Nullable; -import java.util.List; - -public class ReactorCooler extends Block implements IWrenchable { - public ReactorCooler(Properties properties) { - super(properties); - } - - - @Override // Called when the block is placed on the world - public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { - super.onPlace(state, level, pos, oldState, movedByPiston); - List players = level.players(); - FindController(pos, level, players, true); - } - - @Override // called when the player destroys the block, with or without a tool - public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { - super.playerDestroy(level, player, pos, state, blockEntity, tool); - List players = level.players(); - FindController(pos, level, players, false); - } - - @Override - public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { - super.onRemove(state, level, pos, newState, movedByPiston); - List players = level.players(); - FindController(pos, level, players, false); - } - - public ReactorControllerBlock FindController(BlockPos blockPos, Level level, List players, boolean first){ // Function that checks the surrounding blocks in order - BlockPos newBlock; // to find the controller and verify the pattern - Vec3i pos = new Vec3i(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - for (int y = pos.getY()-3; y != pos.getY()+4; y+=1) { - for (int x = pos.getX()-5; x != pos.getX()+5; x+=1) { - for (int z = pos.getZ()-5; z != pos.getZ()+5; z+=1) { - newBlock = new BlockPos(x, y, z); - if (level.getBlockState(newBlock).is(CNBlocks.REACTOR_CONTROLLER.get())) { // verifying the pattern - ReactorControllerBlock controller = (ReactorControllerBlock) level.getBlockState(newBlock).getBlock(); - controller.Verify(level.getBlockState(newBlock), newBlock, level, players, first); - ReactorControllerBlockEntity entity = controller.getBlockEntity(level, newBlock); - if (entity.created) { - return controller; - } - } - } - } - } - return null; - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/DefaultHeatCalculator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/DefaultHeatCalculator.java new file mode 100644 index 0000000..c51c075 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/DefaultHeatCalculator.java @@ -0,0 +1,111 @@ +package net.nuclearteam.createnuclear.content.multiblock.reactorLogic; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.items.ItemStackHandler; +import net.nuclearteam.createnuclear.api.multiblock.fluid.ReactorFluidType; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType.TypeRod; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType.TypeRodPredicate; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintItem; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerInventory; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DefaultHeatCalculator implements IHeatCalculator { + private static final int[][] FORMATTED_PATTERN = new int[][]{ + {99,99,99,0,1,2,99,99,99}, + {99,99,3,4,5,6,7,99,99}, + {99,8,9,10,11,12,13,14,99}, + {15,16,17,18,19,20,21,22,23}, + {24,25,26,27,28,29,30,31,32}, + {33,34,35,36,37,38,39,40,41}, + {99,42,43,44,45,46,47,48,99}, + {99,99,49,50,51,52,53,99,99}, + {99,99,99,54,55,56,99,99,99} + }; + private static final int[][] OFFSETS = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} }; + + private static final Map> NEIGHBORS_BY_SLOT = buildNeighborsBySlot(); + + private static Map> buildNeighborsBySlot() { + Map> result = new HashMap<>(); + for (int row = 0; row < FORMATTED_PATTERN.length; row++) { + for (int col = 0; col < FORMATTED_PATTERN[row].length; col++) { + int slot = FORMATTED_PATTERN[row][col]; + if (slot == 99) continue; + + List neighbors = new ArrayList<>(); + for (int[] offset : OFFSETS) { + int nj = row + offset[0]; + int nk = col + offset[1]; + + if (nj < 0 || nj >= FORMATTED_PATTERN.length || nk < 0 || nk >= FORMATTED_PATTERN[nj].length) continue; + + int neighborSlot = FORMATTED_PATTERN[nj][nk]; + if (neighborSlot != 99) neighbors.add(neighborSlot); + } + + result.put(slot, neighbors); + } + } + + return result; + } + + @Override + public double computeHeat(BigFluidStack bigFluidStack, ReactorFluidType type, ReactorControllerInventory inventory, double overHeat, ReactorDisplayState displayState, Level level) { + double heat = 0; + + ItemStackHandler pattern = ReactorBluePrintItem.getItemStorage(inventory.getStackInSlot(0)); + + Map availableItems = displayState != null && displayState.items() != null + ? new HashMap<>(displayState.items()) + : new HashMap<>(); + + Map actualRods = new HashMap<>(); + + for (int slot = 0; slot < pattern.getSlots(); slot++) { + ItemStack currentStack = pattern.getStackInSlot(slot); + if (currentStack.isEmpty()) continue; + + Item rodItem = currentStack.getItem(); + if (availableItems.getOrDefault(rodItem, 0) > 0) { + availableItems.put(rodItem, availableItems.get(rodItem) - 1); + actualRods.put(slot, currentStack); + } + } + + for (Map.Entry entry : actualRods.entrySet()) { + int slot = entry.getKey(); + ItemStack currentStack = entry.getValue(); + RodType rod = RodType.resolveRodType(currentStack.getItem(), level); + + if (!rod.isNotEmptyItem() || rod.type() == TypeRod.NONE) continue; + + heat += rod.baseRodHeat().get(); + + // find position in formattedPattern and check neighbors + for (int neighborSlot : NEIGHBORS_BY_SLOT.getOrDefault(slot, List.of())) { + ItemStack neighborStack = actualRods.get(neighborSlot); + if (neighborStack == null) continue; + + RodType neighborRod = RodType.resolveRodType(neighborStack.getItem(), level); + if (!neighborRod.isNotEmptyItem()) continue; + + if (TypeRodPredicate.isFuel(rod) && TypeRodPredicate.isFuel(neighborRod)) { + heat += rod.proximityRodHeat().get(); + } else if (TypeRodPredicate.isCooled(rod) && TypeRodPredicate.isFuel(neighborRod)) { + heat += neighborRod.baseRodHeat().get() * rod.proximityRodHeat().get(); + } + } + } + return Math.max(0, heat + overHeat); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/DefaultOverheatController.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/DefaultOverheatController.java new file mode 100644 index 0000000..54ab6e6 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/DefaultOverheatController.java @@ -0,0 +1,45 @@ +package net.nuclearteam.createnuclear.content.multiblock.reactorLogic; + +import net.nuclearteam.createnuclear.api.multiblock.fluid.ReactorFluidType; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; + +class DefaultOverheatController implements IOverheatController { + private int overFlowHeatTimer = 0; + private int overFlowLimiter = 30; + private double overHeat = 0; + + private final int liquidTimer = 3600; + + @Override + public void updateState(HeatBalance heatBalance, int currentHeat, BigFluidStack bigFluidStack, ReactorFluidType type) { + int fluidAmount = bigFluidStack == null ? 0 : bigFluidStack.amount; + int fluidEfficiency = type == null ? -1 : type.efficiency(); + boolean exceedsFluidMaxHeat = type != null && Math.abs(currentHeat) > type.maxHeat(); + + boolean rodMalus = heatBalance.resolve() == EquilibriumState.OVERHEATING; + boolean fluidMalus = fluidEfficiency == -1 || fluidAmount < fluidEfficiency || exceedsFluidMaxHeat; + + int malusPoints = (rodMalus ? 1 : 0) + (fluidMalus ? 1 : 0); + + if (malusPoints > 0) { + overFlowHeatTimer++; + if (overFlowHeatTimer >= overFlowLimiter) { + overHeat += malusPoints; + overFlowHeatTimer = 0; + overFlowLimiter = Math.max(2, overFlowLimiter - malusPoints); + } + } else { + overFlowHeatTimer = 0; + overFlowLimiter = 30; + if (overHeat > 0) overHeat -= 2; + else overHeat = 0; + } + } + + @Override + public double getOverHeat() { return overHeat; } + + + @Override + public int getLiquidTimer() { return liquidTimer; } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/EquilibriumState.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/EquilibriumState.java new file mode 100644 index 0000000..3dbe6ea --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/EquilibriumState.java @@ -0,0 +1,21 @@ +package net.nuclearteam.createnuclear.content.multiblock.reactorLogic; + +/** + * Reactor thermal equilibrium state, derived from the fuel:cooler ratio + * (wiki reference: {@code heatPoints / coolingPoints} ratio compared to 6). + *

+ * Only {@link #OVERHEATING} is currently consumed by + * {@link DefaultOverheatController} (triggers the escalation toward + * shutdown/explosion). {@link #BALANCED} and {@link #OVERCOOLING} are kept + * for future versions (wiki-style status display, output bonus/malus) but + * have no effect on overheating today: a reactor in overcooling is simply + * suboptimal (less heat produced), not penalized. + */ +public enum EquilibriumState { + /** ratio > 6:1 — too much fuel for the cooling, leads to explosion. */ + OVERHEATING, + /** ratio == 6:1 — exact wiki equilibrium. */ + BALANCED, + /** ratio < 6:1 — safe but suboptimal output, no malus. */ + OVERCOOLING +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/HeatBalance.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/HeatBalance.java new file mode 100644 index 0000000..ea6b3f9 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/HeatBalance.java @@ -0,0 +1,34 @@ +package net.nuclearteam.createnuclear.content.multiblock.reactorLogic; + +/** + * Thermal balance of a pattern: heat points (fuel) and cooling points + * (cooler), each weighted by {@link net.nuclearteam.createnuclear.api.multiblock.rods.RodType#ratio()}. + *

+ * Since {@code graphiteHeatRatio} switched to a positive value (1), + * {@code heatPoints} and {@code coolingPoints} are both raw positive sums + * (e.g. uranium=2/rod, thorium=1/rod, graphite=1/rod) — the 6:1 equilibrium + * ratio (wiki reference) is therefore no longer implicit in the config and + * must be compared explicitly via {@link #TARGET_RATIO}. + */ +public record HeatBalance(int heatPoints, int coolingPoints) { + /** Reference fuel:cooler ratio (wiki) at equilibrium. */ + public static final int TARGET_RATIO = 6; + + /** + * Resolves the equilibrium state from this balance. + * + * @return {@link EquilibriumState#OVERHEATING} if no cooler is present + * while there is fuel, otherwise the state corresponding to the + * comparison of {@code heatPoints / coolingPoints} against + * {@link #TARGET_RATIO} + */ + public EquilibriumState resolve() { + if (coolingPoints == 0) return heatPoints() > 0 ? EquilibriumState.OVERHEATING : EquilibriumState.BALANCED; + + double ration = (double) heatPoints() / coolingPoints(); + if (ration > TARGET_RATIO) return EquilibriumState.OVERHEATING; + if (ration < TARGET_RATIO) return EquilibriumState.OVERCOOLING; + + return EquilibriumState.BALANCED; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/HeatManager.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/HeatManager.java new file mode 100644 index 0000000..e546466 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/HeatManager.java @@ -0,0 +1,33 @@ +package net.nuclearteam.createnuclear.content.multiblock.reactorLogic; + +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.api.multiblock.fluid.ReactorFluidType; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerInventory; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; + +/** + * HeatManager facade delegating to extracted components (in separate files). + */ +public class HeatManager { + private final IHeatCalculator calculator; + private final IOverheatController overheatController; + + public HeatManager(IHeatCalculator calculator, IOverheatController overheatController) { + this.calculator = calculator; + this.overheatController = overheatController; + } + + public HeatManager() { + this(new DefaultHeatCalculator(), new DefaultOverheatController()); + } + + public double calculateHeat(BigFluidStack bigFluidStack, HeatBalance heatBalance, int previousHeat, ReactorControllerInventory inventory, Level level, ReactorDisplayState displayState) { + ReactorFluidType type = bigFluidStack == null ? null : bigFluidStack.getFluidtype(level); + overheatController.updateState(heatBalance, previousHeat, bigFluidStack, type); + + return calculator.computeHeat(bigFluidStack, type, inventory, overheatController.getOverHeat(), displayState, level); + } + + public int getLiquidTimer() { return overheatController.getLiquidTimer();} +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/IHeatCalculator.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/IHeatCalculator.java new file mode 100644 index 0000000..09dbba9 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/IHeatCalculator.java @@ -0,0 +1,11 @@ +package net.nuclearteam.createnuclear.content.multiblock.reactorLogic; + +import net.minecraft.world.level.Level; +import net.nuclearteam.createnuclear.api.multiblock.fluid.ReactorFluidType; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerInventory; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; + +public interface IHeatCalculator { + double computeHeat(BigFluidStack bigFluidStack, ReactorFluidType type, ReactorControllerInventory inventory, double overHeat, ReactorDisplayState displayState, Level level); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/IOverheatController.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/IOverheatController.java new file mode 100644 index 0000000..62090d5 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/reactorLogic/IOverheatController.java @@ -0,0 +1,10 @@ +package net.nuclearteam.createnuclear.content.multiblock.reactorLogic; + +import net.nuclearteam.createnuclear.api.multiblock.fluid.ReactorFluidType; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; + +public interface IOverheatController { + void updateState(HeatBalance heatBalance, int currentHeat, BigFluidStack bigFluidStack, ReactorFluidType type); + double getOverHeat(); + int getLiquidTimer(); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/rod/CNRodTypes.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/rod/CNRodTypes.java new file mode 100644 index 0000000..5a7a478 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/rod/CNRodTypes.java @@ -0,0 +1,41 @@ +package net.nuclearteam.createnuclear.content.multiblock.rod; + +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.CreateNuclearRegistries; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; + +import static net.nuclearteam.createnuclear.api.ItemRodTypesValue.DEFAULT_ROD_TYPE; + +public class CNRodTypes { + /** + * Static registry of rod types ({@code RodType}) for the CreateNuclear mod. + * + *

This class exposes the {@link ResourceKey}s and the {@code bootstrap} + * method invoked by the datapack system to register rod types used by the + * multiblock (for example, fuel rods and cooler rods). The examples below + * show how to create a {@code RodType} via its {@code RodType.Builder}.

+ * + *

Example — Custom Rod:

+ *
{@code
+     * register(ctx, "name", new RodType.Builder()
+     *     .baseRodHeat(int)
+     *     .proximityRodHeat(int)
+     *     .rodTimer(int)
+     *     .item(Item)
+     *     .fuelRodType()
+     *     .build());
+     * }
+ * + * @see RodType + * @see CreateNuclearRegistries + */ + public static void bootstrap(BootstrapContext ctx) { + register(ctx, "fallback", DEFAULT_ROD_TYPE); + } + + private static void register(BootstrapContext ctx, String name, RodType type) { + ctx.register(ResourceKey.create(CreateNuclearRegistries.ROD_TYPE, CreateNuclear.asResource(name)), type); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticles.java b/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticles.java new file mode 100644 index 0000000..a3f2a58 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticles.java @@ -0,0 +1,50 @@ +package net.nuclearteam.createnuclear.content.particles; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; +import net.minecraft.util.RandomSource; + +import javax.annotation.Nullable; + +public class IrradiatedParticles extends TextureSheetParticle { + protected IrradiatedParticles(ClientLevel pLevel, double pX, double pY, double pZ, + SpriteSet spriteSet, double pXSpeed, double pYSpeed, double pZSpeed) { + super(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed); + + RandomSource randomSource = level.random; + + this.xo = randomSource.nextGaussian() * (double)1.0E-6f; + this.yo = randomSource.nextGaussian() * (double)1.0E-4f; + this.zo = randomSource.nextGaussian() * (double)1.0E-6f; + + this.quadSize *= this.random.nextFloat() * 0.6f + 0.6f; + this.hasPhysics = false; + this.gravity = 0.0f; + + this.friction = 0.8f; + this.lifetime = 40; + + this.setSpriteFromAge(spriteSet); + + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; + } + + public static class Provider implements ParticleProvider { + private final SpriteSet spriteSet; + + public Provider(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + @Nullable + @Override + public Particle createParticle(IrradiatedParticlesData pType, ClientLevel pLevel, double pX, double pY, double pZ, + double pXSpeed, double pYSpeed, double pZSpeed) { + return new IrradiatedParticles(pLevel, pX, pY, pZ, this.spriteSet, pXSpeed, pYSpeed, pZSpeed); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticlesData.java b/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticlesData.java new file mode 100644 index 0000000..22fcb05 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticlesData.java @@ -0,0 +1,68 @@ +package net.nuclearteam.createnuclear.content.particles; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.foundation.particle.ICustomParticleDataWithSprite; +import net.minecraft.client.particle.ParticleEngine.SpriteParticleRegistration; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.nuclearteam.createnuclear.CNParticleTypes; + +import java.util.Locale; + +public class IrradiatedParticlesData implements ParticleOptions, ICustomParticleDataWithSprite { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(i -> + i.group( + Codec.INT.optionalFieldOf("t", 0).forGetter(p -> p.t) + ) + .apply(i, IrradiatedParticlesData::new) + ); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.INT, + p -> p.t, + IrradiatedParticlesData::new + ); + + int t; + + public IrradiatedParticlesData(int _t) { + t = _t; + } + + public IrradiatedParticlesData() { + this(0); + } + + @Override + public ParticleType getType() { + return CNParticleTypes.IRRADIATED_PARTICLES.get(); + } + + public void writeToNetwork(FriendlyByteBuf buffer) { + buffer.writeInt(t); + } + + public String writeToString() { + return String.format(Locale.ROOT, "%s %d", CNParticleTypes.IRRADIATED_PARTICLES.parameter(), t); + } + + public MapCodec getCodec(ParticleType type) { + return CODEC; + } + + public StreamCodec getStreamCodec() { + return STREAM_CODEC; + } + + @Override + public SpriteParticleRegistration getMetaFactory() { + return IrradiatedParticles.Provider::new; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/particles/NuclearMushroomCloudModel.java b/src/main/java/net/nuclearteam/createnuclear/content/particles/NuclearMushroomCloudModel.java new file mode 100644 index 0000000..dbc75c7 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/particles/NuclearMushroomCloudModel.java @@ -0,0 +1,213 @@ +package net.nuclearteam.createnuclear.content.particles; + +import com.google.common.collect.ImmutableList; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.nuclearteam.createnuclear.content.explosion.CNAdvancedEntityModel; +import net.nuclearteam.createnuclear.content.explosion.CNAdvancedModelBox; +import net.nuclearteam.createnuclear.content.explosion.CNBasicModelPart; + +public class NuclearMushroomCloudModel extends CNAdvancedEntityModel { + private final CNAdvancedModelBox mushroom_cloud; + private final CNAdvancedModelBox lightBall; + private final CNAdvancedModelBox lowerCloud; + private final CNAdvancedModelBox lowerCloud_planes; + private final CNAdvancedModelBox cube_r1; + private final CNAdvancedModelBox cube_r2; + private final CNAdvancedModelBox cube_r3; + private final CNAdvancedModelBox cube_r4; + private final CNAdvancedModelBox plume; + private final CNAdvancedModelBox cube_r5; + private final CNAdvancedModelBox cube_r6; + private final CNAdvancedModelBox plumeBlast; + private final CNAdvancedModelBox plumeRing; + private final CNAdvancedModelBox upperCloud; + private final CNAdvancedModelBox upperCloud1; + private final CNAdvancedModelBox upperCloud_planes; + private final CNAdvancedModelBox cube_r7; + private final CNAdvancedModelBox cube_r8; + private final CNAdvancedModelBox cube_r9; + private final CNAdvancedModelBox cube_r10; + private final CNAdvancedModelBox rings; + private final CNAdvancedModelBox upperRing; + private final CNAdvancedModelBox lowerRing; + + public NuclearMushroomCloudModel() { + texWidth = 512; + texHeight = 512; + + mushroom_cloud = new CNAdvancedModelBox(this); + mushroom_cloud.setRotationPoint(0.0F, 24.0F, 0.0F); + + + lightBall = new CNAdvancedModelBox(this); + lightBall.setRotationPoint(0.0F, -19.0F, 0.0F); + mushroom_cloud.addChild(lightBall); + lightBall.setTextureOffset(300, 0).addBox(-16.0F, -16.0F, -16.0F, 32.0F, 32.0F, 32.0F, 0.0F, false); + + lowerCloud = new CNAdvancedModelBox(this); + lowerCloud.setRotationPoint(0.0F, 5.0F, 0.0F); + lightBall.addChild(lowerCloud); + lowerCloud.setTextureOffset(0, 0).addBox(-50.0F, -9.0F, -50.0F, 100.0F, 16.0F, 100.0F, 0.0F, false); + + lowerCloud_planes = new CNAdvancedModelBox(this); + lowerCloud_planes.setRotationPoint(0.0F, 0.0F, 0.0F); + lowerCloud.addChild(lowerCloud_planes); + + + cube_r1 = new CNAdvancedModelBox(this); + cube_r1.setRotationPoint(-16.0F, -20.0F, 16.0F); + lowerCloud_planes.addChild(cube_r1); + setRotateAngle(cube_r1, 0.0F, 0.7854F, 0.0F); + cube_r1.setTextureOffset(142, 342).addBox(-66.0F, -13.0F, 0.0F, 66.0F, 40.0F, 0.0F, 0.0F, true); + + cube_r2 = new CNAdvancedModelBox(this); + cube_r2.setRotationPoint(16.0F, -20.0F, -16.0F); + lowerCloud_planes.addChild(cube_r2); + setRotateAngle(cube_r2, 0.0F, 0.7854F, 0.0F); + cube_r2.setTextureOffset(142, 342).addBox(0.0F, -13.0F, 0.0F, 66.0F, 40.0F, 0.0F, 0.0F, false); + + cube_r3 = new CNAdvancedModelBox(this); + cube_r3.setRotationPoint(16.0F, -20.0F, 16.0F); + lowerCloud_planes.addChild(cube_r3); + setRotateAngle(cube_r3, 0.0F, -0.7854F, 0.0F); + cube_r3.setTextureOffset(142, 342).addBox(0.0F, -13.0F, 0.0F, 66.0F, 40.0F, 0.0F, 0.0F, false); + + cube_r4 = new CNAdvancedModelBox(this); + cube_r4.setRotationPoint(-16.0F, -20.0F, -16.0F); + lowerCloud_planes.addChild(cube_r4); + setRotateAngle(cube_r4, 0.0F, -0.7854F, 0.0F); + cube_r4.setTextureOffset(142, 342).addBox(-66.0F, -13.0F, 0.0F, 66.0F, 40.0F, 0.0F, 0.0F, true); + + plume = new CNAdvancedModelBox(this); + plume.setRotationPoint(0.0F, 9, 0.0F); + lightBall.addChild(plume); + + + cube_r5 = new CNAdvancedModelBox(this); + cube_r5.setRotationPoint(0.0F, -44.8333F, 0.0F); + plume.addChild(cube_r5); + setRotateAngle(cube_r5, 0.0F, -0.7854F, 0.0F); + cube_r5.setTextureOffset(256, 220).addBox(-32.0F, -61.0F, 0.0F, 64.0F, 122.0F, 0.0F, 0.0F, false); + + cube_r6 = new CNAdvancedModelBox(this); + cube_r6.setRotationPoint(0.0F, -44.8333F, 0.0F); + plume.addChild(cube_r6); + setRotateAngle(cube_r6, 0.0F, 0.7854F, 0.0F); + cube_r6.setTextureOffset(256, 220).addBox(-32.0F, -61.0F, 0.0F, 64.0F, 122.0F, 0.0F, 0.0F, false); + + plumeBlast = new CNAdvancedModelBox(this); + plumeBlast.setRotationPoint(0.0F, -80.8333F, 0.0F); + plume.addChild(plumeBlast); + plumeBlast.setTextureOffset(240, 116).addBox(-18.0F, 0.0F, -18.0F, 36.0F, 29.0F, 36.0F, 0.0F, false); + + plumeRing = new CNAdvancedModelBox(this); + plumeRing.setRotationPoint(0.0F, -35.8333F, 0.0F); + plume.addChild(plumeRing); + plumeRing.setTextureOffset(296, 440).addBox(-36.0F, 0.0F, -36.0F, 72.0F, 0.0F, 72.0F, 0.0F, false); + + upperCloud = new CNAdvancedModelBox(this); + upperCloud.setRotationPoint(0.0F, -80.8333F, 0.0F); + plume.addChild(upperCloud); + upperCloud.setTextureOffset(0, 116).addBox(-40.0F, -24.0F, -40.0F, 80.0F, 24.0F, 80.0F, 0.0F, false); + + upperCloud1 = new CNAdvancedModelBox(this); + upperCloud1.setRotationPoint(0.0F, -24.0F, 0.0F); + upperCloud.addChild(upperCloud1); + upperCloud1.setTextureOffset(0, 220).addBox(-32.0F, -15.0F, -32.0F, 64.0F, 15.0F, 64.0F, 0.0F, false); + + upperCloud_planes = new CNAdvancedModelBox(this); + upperCloud_planes.setRotationPoint(0.0F, -12.0F, 0.0F); + upperCloud.addChild(upperCloud_planes); + + + cube_r7 = new CNAdvancedModelBox(this); + cube_r7.setRotationPoint(16.0F, 112.0F, -16.0F); + upperCloud_planes.addChild(cube_r7); + setRotateAngle(cube_r7, 0.0F, 0.7854F, 0.0F); + cube_r7.setTextureOffset(0, 299).addBox(-23.0F, -152.0F, 0.0F, 71.0F, 69.0F, 0.0F, 0.0F, false); + + cube_r8 = new CNAdvancedModelBox(this); + cube_r8.setRotationPoint(16.0F, 112.0F, 16.0F); + upperCloud_planes.addChild(cube_r8); + setRotateAngle(cube_r8, 0.0F, -0.7854F, 0.0F); + cube_r8.setTextureOffset(0, 299).addBox(-23.0F, -152.0F, 0.0F, 71.0F, 69.0F, 0.0F, 0.0F, false); + + cube_r9 = new CNAdvancedModelBox(this); + cube_r9.setRotationPoint(-16.0F, 112.0F, 16.0F); + upperCloud_planes.addChild(cube_r9); + setRotateAngle(cube_r9, 0.0F, 0.7854F, 0.0F); + cube_r9.setTextureOffset(0, 299).addBox(-48.0F, -152.0F, 0.0F, 71.0F, 69.0F, 0.0F, 0.0F, true); + + cube_r10 = new CNAdvancedModelBox(this); + cube_r10.setRotationPoint(-16.0F, 112.0F, -16.0F); + upperCloud_planes.addChild(cube_r10); + setRotateAngle(cube_r10, 0.0F, -0.7854F, 0.0F); + cube_r10.setTextureOffset(0, 299).addBox(-48.0F, -152.0F, 0.0F, 71.0F, 69.0F, 0.0F, 0.0F, true); + + rings = new CNAdvancedModelBox(this); + rings.setRotationPoint(0.0F, -55.0F, 0.0F); + upperCloud.addChild(rings); + + + upperRing = new CNAdvancedModelBox(this); + upperRing.setRotationPoint(0.0F, -4.0F, 0.0F); + rings.addChild(upperRing); + upperRing.setTextureOffset(296, 440).addBox(-36.0F, 0.0F, -36.0F, 72.0F, 0.0F, 72.0F, 0.0F, false); + + lowerRing = new CNAdvancedModelBox(this); + lowerRing.setRotationPoint(0.0F, 4.0F, 0.0F); + rings.addChild(lowerRing); + lowerRing.setTextureOffset(296, 440).addBox(-36.0F, 0.0F, -36.0F, 72.0F, 0.0F, 72.0F, 0.0F, false); + this.updateDefaultPose(); + } + + + @Override + public Iterable parts() { + return ImmutableList.of(mushroom_cloud); + } + + @Override + public Iterable getAllParts() { + return ImmutableList.of(rings, mushroom_cloud, lowerCloud, lowerCloud_planes, lightBall, cube_r1, cube_r2, cube_r3, cube_r4, cube_r5, cube_r6, cube_r7, cube_r8, cube_r9, cube_r10, plume, plumeBlast, plumeRing, upperCloud, upperCloud_planes, upperCloud1, upperRing, lowerRing); + } + + + @Override + public void setupAnim(Entity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + this.resetToDefaultPose(); + } + + public void hideFireball(boolean fireball) { + this.plume.showModel = fireball; + this.lowerCloud.showModel = fireball; + this.upperCloud.showModel = fireball; + } + + public void animateParticle(float age, float life, float partialTicks) { + this.resetToDefaultPose(); + float lerpedAge = age + partialTicks; + float baseExpand1 = life + life * life; + float upperExpand = offset(life, 0.3F, 0.4F, 1.5F); + float plumeRingExpand = offset(life, 0.0F, 0.0F, 0.5F) * 45; + float lowerRingExpand = offset(life, 0.0F, 0.1F, 0.65F) * 20; + float upperRingExpand = offset(life, 0.0F, 0.2F, 0.65F) * 15; + this.plume.scaleChildren = true; + this.upperCloud.scaleChildren = true; + this.lowerCloud.scaleChildren = true; + this.plume.setScale(1, life * 1.5F, 1); + this.upperCloud.setScale(upperExpand, 1, upperExpand); + this.plumeRing.setScale(plumeRingExpand, 1, plumeRingExpand); + this.lowerRing.setScale(lowerRingExpand, 1, lowerRingExpand); + this.upperRing.setScale(upperRingExpand, 1, upperRingExpand); + this.lowerCloud.setScale(baseExpand1, baseExpand1, baseExpand1); + this.plumeRing.rotateAngleY += lerpedAge * 0.1; + this.lowerRing.rotateAngleY -= lerpedAge * 0.2; + this.upperRing.rotateAngleY += lerpedAge * 0.1; + } + + public float offset(float life, float forwards, float min, float max) { + return Mth.clamp(life + forwards, min, max); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/particles/NuclearMushroomCloudParticle.java b/src/main/java/net/nuclearteam/createnuclear/content/particles/NuclearMushroomCloudParticle.java new file mode 100644 index 0000000..9abc3cf --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/particles/NuclearMushroomCloudParticle.java @@ -0,0 +1,137 @@ +package net.nuclearteam.createnuclear.content.particles; + +import net.nuclearteam.createnuclear.*; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleProvider; +import net.minecraft.client.particle.ParticleRenderType; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; +import net.nuclearteam.createnuclear.content.explosion.CNNuclearExplosionSound; +import net.nuclearteam.createnuclear.foundation.utility.Maths; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; + +public class NuclearMushroomCloudParticle extends Particle { + + private static final ResourceLocation TEXTURE = CreateNuclear.asResource("textures/particle/nuclear_mushroom_cloud.png"); + private static final ResourceLocation TEXTURE_GLOW = CreateNuclear.asResource("textures/particle/nuclear_mushroom_cloud_glow.png"); + private static final ResourceLocation TEXTURE_PINK = CreateNuclear.asResource("textures/particle/nuclear_mushroom_cloud_pink.png"); + private static final ResourceLocation TEXTURE_PINK_GLOW = CreateNuclear.asResource("textures/particle/nuclear_mushroom_cloud_pink_glow.png"); + private static final NuclearMushroomCloudModel MODEL = new NuclearMushroomCloudModel(); + private static final int BALL_FOR = 10; + private static final int GLOW_FOR = 20; + private static final int FADE_SPEED = 10; + private final float scale; + + private boolean playedRinging; + private boolean playedExplosion; + private boolean playedRumble; + + private final boolean pink; + + protected NuclearMushroomCloudParticle(ClientLevel level, double x, double y, double z, float scale, boolean pink) { + super(level, x, y, z); + this.gravity = 0.0F; + this.lifetime = (int) Math.ceil(133.33F * scale); + this.scale = scale + 0.2F; + this.setSize(3.0F, 3.0F); + this.pink = pink; + } + + public boolean shouldCull() { + return false; + } + + public void tick() { + CNClientProxy.renderNukeSkyDarkFor = 70; + CNClientProxy.muteNonNukeSoundsFor = 50; + boolean large = this.scale > 2.0F; + if(age > BALL_FOR / 2 + 5){ + if(!playedExplosion){ + playedExplosion = true; + CreateNuclear.LOGGER.info("EXPLOSIOOOOOON"); + playSound(CNSoundEvents.NUCLEAR_EXPLOSION_MAIN.getMainEvent(), lifetime - 20, lifetime, 0.2F, false); + } + } + if (age < BALL_FOR) { + if (!playedRinging && CNConfigs.client().nuclearBombFlash.get()) { + playedRinging = true; + playSound(CNSoundEvents.NUCLEAR_EXPLOSION_RINGING.getMainEvent(), 100, 50, 0.05F, true); + // playSound(CNSoundEvents.NUCLEAR_EXPLOSION_SHOCKWAVE.getMainEvent(), 100, 50, 0.05F, true); + } + CNClientProxy.renderNukeFlashFor = 16; + } else if (age < lifetime - FADE_SPEED) { + float life = (float) (Math.log(1 + (age - BALL_FOR) / (float) (lifetime - BALL_FOR))) * 2F; + float explosionSpread = (12 * life + 4F) * scale; + for (int i = 0; i < (1 + random.nextInt(2)) * scale; i++) { + Vec3 from = new Vec3(level.random.nextFloat() - 0.5F, level.random.nextFloat() - 0.5F, level.random.nextFloat() - 0.5F).scale(scale * 1.4F).add(this.x, this.y, this.z); + Vec3 away = new Vec3(level.random.nextFloat() - 0.5F, level.random.nextFloat() - 0.5F, level.random.nextFloat() - 0.5F).scale(2.34F); + this.level.addParticle(CNParticleRegistry.NUCLEAR_MUSHROOM_CLOUD_SMOKE.get(), from.x, from.y, from.z, away.x, away.y, away.z); + } + for (int j = 0; j < scale * scale; j++) { + Vec3 explosionBase = new Vec3((level.random.nextFloat() - 0.5F) * explosionSpread, (-0.6F + level.random.nextFloat() * 0.5F) * explosionSpread * 0.1F, (level.random.nextFloat() - 0.5F) * explosionSpread).add(this.x, this.y, this.z); + this.level.addParticle(CNParticleRegistry.NUCLEAR_MUSHROOM_CLOUD_EXPLOSION.get(), explosionBase.x, explosionBase.y, explosionBase.z, 0, 0, 0); + } + if(age > BALL_FOR){ + if(!playedRumble){ + playedRumble = true; + + playSound(CNSoundEvents.NUCLEAR_EXPLOSION_RUMBLE_2.getMainEvent(), lifetime + 100, lifetime, 0.1F, true); + } + } + } + super.tick(); + } + + private void playSound(SoundEvent soundEvent, int duration, int fadesAt, float fadeInBy, boolean looping){ + Minecraft.getInstance().getSoundManager().queueTickingSound(new CNNuclearExplosionSound(soundEvent, this.x, this.y, this.z, duration, fadesAt, fadeInBy, looping)); + } + + public void render(VertexConsumer vertexConsumer, Camera camera, float partialTick) { + Vec3 vec3 = camera.getPosition(); + float f = (float) (Mth.lerp((double) partialTick, this.xo, this.x) - vec3.x()); + float f1 = (float) (Mth.lerp((double) partialTick, this.yo, this.y) - vec3.y()); + float f2 = (float) (Mth.lerp((double) partialTick, this.zo, this.z) - vec3.z()); + PoseStack posestack = new PoseStack(); + posestack.pushPose(); + posestack.translate(f, f1 - 0.5F, f2); + posestack.scale(-scale, -scale, scale); + MultiBufferSource.BufferSource multibuffersource$buffersource = Minecraft.getInstance().renderBuffers().bufferSource(); + MODEL.hideFireball(age >= BALL_FOR); + float life = (float) (Math.log(1 + (age - BALL_FOR + partialTick) / (lifetime - BALL_FOR))) * 2F; + float glowLife = life < 1F ? 1F - life : 0; + int left = lifetime - age; + float alpha = left <= FADE_SPEED ? left / (float) FADE_SPEED : 1.0F; + MODEL.animateParticle(age, Maths.smin(life, 1.0F, 0.5F), partialTick); + VertexConsumer baseConsumer = multibuffersource$buffersource.getBuffer(RenderType.entityTranslucent(pink ? TEXTURE_PINK : TEXTURE)); + int color = ((int)(alpha * 255.0F) << 24) | 0xFFFFFF; + MODEL.renderToBuffer(posestack, baseConsumer, getLightColor(partialTick), OverlayTexture.NO_OVERLAY, color); + multibuffersource$buffersource.endBatch(); + posestack.popPose(); + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.CUSTOM; + } + + public static class Factory implements ParticleProvider { + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + if (xSpeed == 0.0) { + xSpeed = 1.0F; + } + return new NuclearMushroomCloudParticle(worldIn, x, y, z, (float) Math.max(0.5F, xSpeed), ySpeed >= 1.0F); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/particles/SmallNuclearExplosionParticle.java b/src/main/java/net/nuclearteam/createnuclear/content/particles/SmallNuclearExplosionParticle.java new file mode 100644 index 0000000..9318a33 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/particles/SmallNuclearExplosionParticle.java @@ -0,0 +1,280 @@ +package net.nuclearteam.createnuclear.content.particles; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.util.FastColor; + +public class SmallNuclearExplosionParticle extends TextureSheetParticle { + + private final SpriteSet sprites; + private boolean hasFadeColor = false; + private float fadeR; + private float fadeG; + private float fadeB; + protected SmallNuclearExplosionParticle(ClientLevel world, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, SpriteSet sprites, boolean shortLifespan, int color1) { + super(world, x, y, z, xSpeed, ySpeed, zSpeed); + this.xd = xSpeed; + this.yd = ySpeed; + this.zd = zSpeed; + this.setSize(0.5F, 0.5F); + this.quadSize = (shortLifespan ? 1 : 0.8F) + world.random.nextFloat() * 0.3F; + this.lifetime = shortLifespan ? 5 + world.random.nextInt(3) : 15 + world.random.nextInt(10); + this.friction = 0.96F; + float randCol = world.random.nextFloat() * 0.05F; + this.sprites = sprites; + this.setColor(Math.min(FastColor.ARGB32.red(color1) / 255F + randCol, 1), Math.min(1F, FastColor.ARGB32.green(color1) / 255F + randCol), Math.min(1F, FastColor.ARGB32.blue(color1) / 255F + randCol)); + } + + public void setFadeColor(int i){ + hasFadeColor = true; + this.fadeR = (float) ((i & 16711680) >> 16) / 255.0F; + this.fadeG = (float) ((i & '\uff00') >> 8) / 255.0F; + this.fadeB = (float) ((i & 255) >> 0) / 255.0F; + } + + public void tick() { + this.xo = this.x; + this.yo = this.y; + this.zo = this.z; + this.setSpriteFromAge(this.sprites); + if (this.age++ >= this.lifetime) { + this.remove(); + } else { + if(hasFadeColor){ + this.rCol += (fadeR - this.rCol) * 0.2F; + this.gCol += (fadeG - this.gCol) * 0.2F; + this.bCol += (fadeB - this.bCol) * 0.2F; + }else{ + this.rCol = this.rCol * 0.95F; + this.gCol = this.gCol * 0.95F; + this.bCol = this.bCol * 0.95F; + } + this.move(this.xd, this.yd, this.zd); + this.xd *= (double) this.friction; + this.yd *= (double) this.friction; + this.zd *= (double) this.friction; + } + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_LIT; + } + + public float getQuadSize(float scaleFactor) { + return super.getQuadSize(scaleFactor); + } + + public int getLightColor(float partialTicks) { + return 240; + } + + public static class NukeFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public NukeFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, false, 0XFFB300); + particle.setSpriteFromAge(spriteSet); + return particle; + } + } + + public static class MineFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public MineFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, true, 0XFFB300); + particle.setSpriteFromAge(spriteSet); + return particle; + } + } + + public static class UnderzealotFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public UnderzealotFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, false, 0); + particle.setSpriteFromAge(spriteSet); + return particle; + } + } + + public static class RaygunFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public RaygunFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, true, 0XEEEEEE); + particle.setSpriteFromAge(spriteSet); + particle.lifetime = 5 + worldIn.random.nextInt(3); + particle.scale(0.6F + worldIn.random.nextFloat() * 0.3F); + particle.setFadeColor(0X40EE40); + return particle; + } + } + + public static class BlueRaygunFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public BlueRaygunFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, true, 0XEEEEEE); + particle.setSpriteFromAge(spriteSet); + particle.lifetime = 5 + worldIn.random.nextInt(5); + particle.scale(0.5F + worldIn.random.nextFloat() * 0.5F); + particle.setFadeColor(0X40EEDA); + return particle; + } + } + + public static class TremorzillaFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public TremorzillaFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, true, 0XEEEEEE); + particle.setSpriteFromAge(spriteSet); + particle.lifetime = 9 + worldIn.random.nextInt(3); + particle.scale(1.0F + worldIn.random.nextFloat() * 0.9F); + particle.setFadeColor(0X9BFF3D); + return particle; + } + } + + public static class TremorzillaRetroFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public TremorzillaRetroFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, true, 0XEEEEEE); + particle.setSpriteFromAge(spriteSet); + particle.lifetime = 9 + worldIn.random.nextInt(3); + particle.scale(1.0F + worldIn.random.nextFloat() * 0.9F); + particle.setFadeColor(0XE06EFF); + return particle; + } + } + + + public static class TremorzillaTectonicFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public TremorzillaTectonicFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, true, 0XEEEEEE); + particle.setSpriteFromAge(spriteSet); + particle.lifetime = 9 + worldIn.random.nextInt(3); + particle.scale(1.0F + worldIn.random.nextFloat() * 0.9F); + particle.setFadeColor(0XFFD631); + return particle; + } + } + + public static class AmberFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public AmberFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, false, 0XFFDA1E); + particle.setSpriteFromAge(spriteSet); + particle.scale(0.8F); + return particle; + } + } + + public static class TotemFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public TotemFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, true, 0XFF0000); + particle.setSpriteFromAge(spriteSet); + particle.lifetime = 5 + worldIn.random.nextInt(3); + particle.scale(1.2F + worldIn.random.nextFloat() * 0.3F); + particle.setFadeColor(0); + return particle; + } + } + + public static class PurpleWitchFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public PurpleWitchFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, true, 0XFF69FF); + particle.setSpriteFromAge(spriteSet); + particle.scale(0.8F); + particle.setFadeColor(0XFFFFFF); + return particle; + } + } + + public static class ConversionCrucibleFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public ConversionCrucibleFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, 0.0D, 0.0D, 0.0D, spriteSet, true, FastColor.ARGB32.color(255, (int)(255F * xSpeed), (int)(255F * ySpeed), (int)(255F * zSpeed))); + particle.setSpriteFromAge(spriteSet); + particle.scale(0.8F); + particle.setFadeColor(0XFFFFFF); + return particle; + } + } + + public static class FrostmintFactory implements ParticleProvider { + private final SpriteSet spriteSet; + + public FrostmintFactory(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + public Particle createParticle(SimpleParticleType typeIn, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + SmallNuclearExplosionParticle particle = new SmallNuclearExplosionParticle(worldIn, x, y, z, xSpeed, ySpeed, zSpeed, spriteSet, true, 0XFFFFFF); + particle.quadSize *= 1.6F; + particle.setSpriteFromAge(spriteSet); + particle.setFadeColor(0XE5F9FA); + return particle; + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/radiation/CNRadiationValues.java b/src/main/java/net/nuclearteam/createnuclear/content/radiation/CNRadiationValues.java new file mode 100644 index 0000000..c419ec1 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/radiation/CNRadiationValues.java @@ -0,0 +1,19 @@ +package net.nuclearteam.createnuclear.content.radiation; + +import com.simibubi.create.AllItems; +import net.nuclearteam.createnuclear.api.radiation.RadiationRegistry; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNBiomes; + +public class CNRadiationValues { + public static void register() { + RadiationRegistry.register() + .item(AllItems.CRUSHED_URANIUM.asItem()) + .value(.5D) + .build(); + + RadiationRegistry.register() + .biome(CNBiomes.Irradiated.PLAIN) + .value(25D) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationBucketItem.java b/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationBucketItem.java new file mode 100644 index 0000000..89d01e5 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationBucketItem.java @@ -0,0 +1,23 @@ +package net.nuclearteam.createnuclear.content.radiation; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.BucketItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.material.Fluid; +import net.nuclearteam.createnuclear.api.radiation.IRadiationSource; + +import java.util.function.Supplier; + +public class RadiationBucketItem extends BucketItem implements IRadiationSource { + private final double radiation; + + public RadiationBucketItem(Fluid fluid, Properties builder, double radiation) { + super(fluid, builder); + this.radiation = radiation; + } + + @Override + public double getRadiation(ItemStack stack, LivingEntity entity) { + return this.radiation; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationEffect.java b/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationEffect.java new file mode 100644 index 0000000..8565f15 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationEffect.java @@ -0,0 +1,79 @@ +package net.nuclearteam.createnuclear.content.radiation; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.world.entity.LivingEntity; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.effects.VicinityEffect; +import net.nuclearteam.createnuclear.content.radiation.capability.RadiationCapability; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.nuclearteam.createnuclear.foundation.damagesTypes.CNDamageSources; + +public class RadiationEffect extends VicinityEffect { + private static final int CONTAGION_DURATION_TICKS = 300; + + /** + * Constructs the RadiationEffect with harmful category and color. + * Also applies attribute modifiers to reduce speed, attack damage, and attack speed. + */ + public RadiationEffect() { + super(MobEffectCategory.HARMFUL, 15453236, + amplifier -> 10, + RadiationCapability::canBeIrradiated, + timer -> {}); // Custom color (hex value) + + // Reduces movement speed by 20% + this.addAttributeModifier( + Attributes.MOVEMENT_SPEED, + ResourceLocation.fromNamespaceAndPath(CreateNuclear.MOD_ID, "radiation_movement_speed"), + -0.2D, + AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL + ); + + // Reduces attack damage by 20% + this.addAttributeModifier( + Attributes.ATTACK_DAMAGE, + ResourceLocation.fromNamespaceAndPath(CreateNuclear.MOD_ID, "radiation_attack_damage"), + -0.2D, + AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL + ); + + // Reduces attack speed by 20% + this.addAttributeModifier( + Attributes.ATTACK_SPEED, + ResourceLocation.fromNamespaceAndPath(CreateNuclear.MOD_ID, "radiation_attack_speed"), + -0.2D, + AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL + ); + } + + @Override + protected void onContaminate(LivingEntity nearby) { + RadiationCapability.applyContagion(nearby, 15D, CONTAGION_DURATION_TICKS); + } + + /** + * Applies the radiation effect to the entity. + * - Does nothing if the entity is immune via tag. + * - Skips damage if the entity is fully protected (anti-radiation armor, iodine effect, ...). + * - Otherwise, applies magic damage based on the amplifier. + * + * @param livingEntity The affected living entity. + * @param amplifier The strength (level) of the effect. + */ + @Override + public boolean applyEffectTick(LivingEntity livingEntity, int amplifier) { + super.applyEffectTick(livingEntity, amplifier); + + double resistance = RadiationCapability.getRadiationResistance(livingEntity); + + float damage = (float) ((1 << amplifier) * (1.0 - resistance)); + + if (damage > 0f) { + livingEntity.hurt(CNDamageSources.radiation(livingEntity.level()), damage); + } + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationEffectHandler.java b/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationEffectHandler.java new file mode 100644 index 0000000..f0ef2ec --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationEffectHandler.java @@ -0,0 +1,25 @@ +package net.nuclearteam.createnuclear.content.radiation; + +import com.simibubi.create.api.effect.OpenPipeEffectHandler; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.neoforged.neoforge.fluids.FluidStack; +import net.nuclearteam.createnuclear.content.radiation.capability.RadiationCapability; + +import java.util.List; + +public class RadiationEffectHandler implements OpenPipeEffectHandler { + private static final double PIPE_LEAK_DOSE = 40.0D; + + @Override + public void apply(Level level, AABB area, FluidStack fluid) { + if (level.getGameTime() % 5 != 0) return; + + List entities = level.getEntitiesOfClass(LivingEntity.class, area, LivingEntity::isAffectedByPotions); + for (LivingEntity entity : entities) { + if (!RadiationCapability.canBeIrradiated(entity)) continue; + RadiationCapability.applyContagion(entity, PIPE_LEAK_DOSE, 20); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationItem.java b/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationItem.java new file mode 100644 index 0000000..e560215 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/radiation/RadiationItem.java @@ -0,0 +1,21 @@ +package net.nuclearteam.createnuclear.content.radiation; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.nuclearteam.createnuclear.api.radiation.IRadiationSource; + +public class RadiationItem extends Item implements IRadiationSource { + + private final double radiation; + + public RadiationItem(Item.Properties settings, double radiation) { + super(settings); + this.radiation = radiation; + } + + @Override + public double getRadiation(ItemStack stack, LivingEntity entity) { + return this.radiation * stack.getCount(); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/radiation/capability/RadiationCapability.java b/src/main/java/net/nuclearteam/createnuclear/content/radiation/capability/RadiationCapability.java new file mode 100644 index 0000000..87a4ddb --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/radiation/capability/RadiationCapability.java @@ -0,0 +1,225 @@ +package net.nuclearteam.createnuclear.content.radiation.capability; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.tick.EntityTickEvent; +import net.nuclearteam.createnuclear.*; +import net.nuclearteam.createnuclear.CNTags.CNEntityTags; +import net.nuclearteam.createnuclear.api.radiation.IRadiationSource; +import net.nuclearteam.createnuclear.api.radiation.RadiationRegistry; +import net.nuclearteam.createnuclear.foundation.utility.ConfigValueResolver; +import net.nuclearteam.createnuclear.foundation.utility.InventoryHashUtil; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; + +import java.util.*; + +@EventBusSubscriber(modid = CreateNuclear.MOD_ID) +public class RadiationCapability { + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + Codec.DOUBLE.optionalFieldOf("radiation", 0D).forGetter(RadiationCapability::getRadiation), + Codec.LONG.optionalFieldOf("hash", 0L).forGetter(RadiationCapability::getInventoryHash), + ResourceLocation.CODEC.optionalFieldOf("lastBiome").forGetter(c -> Optional.ofNullable(c.getLastBiomeLocation())), + Codec.DOUBLE.optionalFieldOf("contagionDose", 0D).forGetter(RadiationCapability::getContagionDose), + Codec.INT.optionalFieldOf("contagionTicks", 0).forGetter(RadiationCapability::getContagionTicks) + ).apply(i, RadiationCapability::create)); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.DOUBLE, RadiationCapability::getRadiation, + ByteBufCodecs.VAR_LONG, RadiationCapability::getInventoryHash, + ByteBufCodecs.optional(ResourceLocation.STREAM_CODEC), c -> Optional.ofNullable(c.getLastBiomeLocation()), + ByteBufCodecs.DOUBLE, RadiationCapability::getContagionDose, + ByteBufCodecs.VAR_INT, RadiationCapability::getContagionTicks, + RadiationCapability::create + ); + + private double radiation; + private long inventoryHash; + private ResourceLocation lastBiomeLocation; + private double contagionDose; + private int contagionTicks; + + public double getRadiation() { return this.radiation; } + public void setRadiation(double value) { this.radiation = value; } + + public long getInventoryHash() { return this.inventoryHash; } + public void setInventoryHash(long hash) { this.inventoryHash = hash; } + + public ResourceLocation getLastBiomeLocation() { return this.lastBiomeLocation; } + public void setLastBiomeLocation(ResourceLocation location) { this.lastBiomeLocation = location; } + + public double getContagionDose() { return this.contagionDose; } + public void setContagionDose(double dose) { this.contagionDose = dose; } + + public int getContagionTicks() { return this.contagionTicks; } + public void setContagionTicks(int ticks) { this.contagionTicks = ticks; } + + private static RadiationCapability create(double radiation, long hash, Optional lastBiome, double contagionDose, int contagionTicks) { + RadiationCapability cap = new RadiationCapability(); + cap.setRadiation(radiation); + cap.setInventoryHash(hash); + cap.setLastBiomeLocation(lastBiome.orElse(null)); + cap.setContagionDose(contagionDose); + cap.setContagionTicks(contagionTicks); + + return cap; + } + + @SubscribeEvent + public static void onEntityTick(EntityTickEvent.Pre event) { + if (event.getEntity() instanceof LivingEntity living) { + tickRadiation(living); + } + } + + public static void applyContagion(LivingEntity entity, double doseValue, int durationTicks) { + RadiationCapability cap = entity.getData(CNAttachmentTypes.RADIATION); + cap.setContagionDose(doseValue); + cap.setContagionTicks(durationTicks); + } + + public static void tickRadiation(LivingEntity entity) { + Level level = entity.level(); + if (level.isClientSide) return; + + // Checked before getData: getData creates and stores the attachment on first access, so + // guarding first keeps immune/blacklisted entities from accumulating one every tick. + if (!canBeIrradiated(entity)) return; + + RadiationCapability cap = entity.getData(CNAttachmentTypes.RADIATION); + + if (entity instanceof Player player) { + long newHash = InventoryHashUtil.compute(player); + if (newHash != cap.getInventoryHash()) { + cap.setInventoryHash(newHash); + cap.setRadiation(Math.max(0, computeItemRadiation(player))); + } + player.syncData(CNAttachmentTypes.RADIATION); + } else { + cap.setRadiation(Math.max(0, computeItemRadiation(entity))); + } + + ResourceKey biomeKey = level.getBiome(entity.blockPosition()).unwrapKey().orElse(null); + ResourceLocation biomeLoc = biomeKey != null ? biomeKey.location() : null; + if (!Objects.equals(biomeLoc, cap.getLastBiomeLocation())) { + cap.setLastBiomeLocation(biomeLoc); + } + + if (cap.getContagionTicks() > 0) { + cap.setContagionTicks(cap.getContagionTicks() - 1); + } + + double contagionDose = cap.getContagionTicks() > 0 ? cap.getContagionDose() : 0; + + double totalRaw = cap.getRadiation() + getRawBiomeRadiation(biomeKey) + contagionDose; + double resistance = getRadiationResistance(entity); + double totalRadiation = totalRaw * (1.0 - resistance); + + applyEffects(entity, totalRadiation); + } + + private static double computeItemRadiation(Player player) { + double radiation = 0; + for (ItemStack stack : player.getInventory().items) { + if (stack.getItem() instanceof IRadiationSource source) + radiation += source.getRadiation(stack, player); + radiation += RadiationRegistry.getRadiation(stack, player); + } + for (ItemStack stack : player.getInventory().offhand) { + if (stack.getItem() instanceof IRadiationSource source) + radiation += source.getRadiation(stack, player); + radiation += RadiationRegistry.getRadiation(stack, player); + } + return radiation; + } + + private static double getStackRadiation(ItemStack stack, LivingEntity entity) { + double radiation = 0; + if (stack.getItem() instanceof IRadiationSource source) radiation += source.getRadiation(stack, entity); + radiation += RadiationRegistry.getRadiation(stack, entity); + return radiation; + } + + private static double computeItemRadiation(LivingEntity entity) { + double radiation = 0; + for (ItemStack stack : entity.getArmorSlots()) { + radiation += getStackRadiation(stack, entity); + } + radiation += getStackRadiation(entity.getMainHandItem(), entity); + radiation += getStackRadiation(entity.getOffhandItem(), entity); + return radiation; + } + + private static double getRawBiomeRadiation(ResourceKey biomeKey) { + if (biomeKey == null) return 0; + return RadiationRegistry.getRadiation(biomeKey, null); + } + + public static boolean canBeIrradiated(LivingEntity entity) { + if (entity.isSpectator()) return false; + if (entity.getType().is(CNEntityTags.IRRADIATED_IMMUNE.tag)) return false; + if (!CNConfigs.server().radiation.enabledItemRadiation.get()) return false; + if (getEntityBlacklist().contains(entity.getType())) return false; + return getRadiationResistance(entity) < 1.0; + } + + private static List cachedBlacklistSource; + private static Set> cachedBlacklist = Set.of(); + + private static Set> getEntityBlacklist() { + List source = CNConfigs.server().radiation.configuredLists.getEntityBlackList(); + if (source != cachedBlacklistSource) { + Set> resolved = new HashSet<>(); + ConfigValueResolver.loadValuesInSet(source, resolved, + entry -> BuiltInRegistries.ENTITY_TYPE.get(ResourceLocation.tryParse(entry))); + cachedBlacklist = resolved; + cachedBlacklistSource = source; + } + return cachedBlacklist; + } + + public static double getRadiationResistance(LivingEntity entity) { + double resistance = 0d; + AttributeInstance attribute = entity.getAttribute(CNAttributes.IRRADIATED_RESISTANCE); + if (attribute != null) resistance += attribute.getValue(); + return Mth.clamp(resistance, 0.0, 1.0); + } + + private static void applyEffects(LivingEntity entity, double radiation) { + final double radiation_desactive = 0; + if (radiation <= radiation_desactive) return; + + int amp; + if (radiation < CNConfigs.server().radiation.radiationLevel1.get()) amp = CNConfigs.server().radiation.amplifierLevel0.get(); + else if (radiation < CNConfigs.server().radiation.radiationLevel2.get()) amp = CNConfigs.server().radiation.amplifierLevel1.get(); + else if (radiation < CNConfigs.server().radiation.radiationLevel3.get()) amp = CNConfigs.server().radiation.amplifierLevel2.get(); + else amp = CNConfigs.server().radiation.amplifierLevel2.get(); + + MobEffectInstance current = entity.getEffect(CNEffects.RADIATION); + + if (current != null && current.getAmplifier() != amp) { + entity.removeEffect(CNEffects.RADIATION); + current = null; + } + + if (current == null || current.getDuration() <= 40) { + entity.addEffect(new MobEffectInstance(CNEffects.RADIATION, 100, amp, true, true)); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/AbstractReactorStatDisplaySource.java b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/AbstractReactorStatDisplaySource.java new file mode 100644 index 0000000..1803ef7 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/AbstractReactorStatDisplaySource.java @@ -0,0 +1,54 @@ +package net.nuclearteam.createnuclear.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.source.NumericSingleLineDisplaySource; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; + +public abstract class AbstractReactorStatDisplaySource extends NumericSingleLineDisplaySource { + protected abstract String getLabelKey(); + protected abstract int getMax(); + protected abstract int computeValue(ReactorControllerBlockEntity controller, DisplayLinkContext context); + protected abstract ChatFormatting getColor(int value, ReactorControllerBlockEntity controller); + protected MutableComponent getUnitSuffix() { return null; } + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + ReactorControllerBlockEntity controller = MultiblockHelpers.getControllerForPart(context.level(), context.getSourcePos()); + if (controller == null || controller.isRemoved()) return ZERO.copy(); + + MutableComponent label = CreateNuclearLang.translateDirect(getLabelKey()).append(" "); + int mode = context.sourceConfig().getInt("display_mode"); + int value = computeValue(controller, context); + int max = getMax(); + ChatFormatting color = getColor(value, controller); + + return label.append(switch (mode) { + case 1 -> Component.literal((value * 100 / max) + "%").withStyle(color); + case 2 -> ReactorGaugeRenderer.drawGauge(value, max, color, 6); + default -> { + MutableComponent base = Component.literal(String.valueOf(value)); + MutableComponent unit = getUnitSuffix(); + yield (unit != null ? base.append(unit) : base).withStyle(color); + } + }); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) { + if (isFirstLine) return; + builder.addSelectionScrollInput(0, 100, (input, l) -> input + .forOptions(CreateNuclearLang.translatedOptions("display_source.reactor.mode", "value", "percent", "gauge")), "display_mode"); + } + + @Override protected boolean allowsLabeling(DisplayLinkContext context) { return true; } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/CoolerDisplaySource.java b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/CoolerDisplaySource.java new file mode 100644 index 0000000..ce7934b --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/CoolerDisplaySource.java @@ -0,0 +1,46 @@ +package net.nuclearteam.createnuclear.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import net.minecraft.ChatFormatting; +import net.minecraft.world.item.Item; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; + +import java.util.Map; + +public class CoolerDisplaySource extends AbstractReactorStatDisplaySource { + + + @Override + protected String getLabelKey() { + return "display_source.reactor.cooler"; + } + + @Override + protected int getMax() { + return ReactorDisplayConstants.MAX_COOLER; + } + + @Override + protected ChatFormatting getColor(int value, ReactorControllerBlockEntity controller) { + return ChatFormatting.AQUA; + } + + @Override + protected int computeValue(ReactorControllerBlockEntity controller, DisplayLinkContext context) { + int cooler = 0; + if (controller.getDisplayState() != null && controller.getDisplayState().items() != null) { + for (Map.Entry entry : controller.getDisplayState().items().entrySet()) { + if (RodType.TypeRodPredicate.isCooled(entry.getKey().getDefaultInstance(), context.level())) { + cooler += entry.getValue(); + } + } + } + return cooler; + } + + @Override + protected String getTranslationKey() { + return "cooler"; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/FuelDisplaySource.java b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/FuelDisplaySource.java new file mode 100644 index 0000000..56a8dc2 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/FuelDisplaySource.java @@ -0,0 +1,45 @@ +package net.nuclearteam.createnuclear.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import net.minecraft.ChatFormatting; +import net.minecraft.world.item.Item; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType.TypeRodPredicate; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; + +import java.util.Map; + +public class FuelDisplaySource extends AbstractReactorStatDisplaySource { + + @Override + protected String getLabelKey() { + return "display_source.reactor.fuel"; + } + + @Override + protected int getMax() { + return ReactorDisplayConstants.MAX_FUEL; + } + + @Override + protected ChatFormatting getColor(int value, ReactorControllerBlockEntity controller) { + return ChatFormatting.GREEN; + } + + @Override + protected int computeValue(ReactorControllerBlockEntity controller, DisplayLinkContext context) { + int fuel = 0; + if (controller.getDisplayState() != null && controller.getDisplayState().items() != null) { + for (Map.Entry entry : controller.getDisplayState().items().entrySet()) { + if (TypeRodPredicate.isFuel(entry.getKey().getDefaultInstance(), context.level())) { + fuel += entry.getValue(); + } + } + } + return fuel; + } + + @Override + protected String getTranslationKey() { + return "fuel"; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/HeatDisplaySource.java b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/HeatDisplaySource.java new file mode 100644 index 0000000..9c58ffb --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/HeatDisplaySource.java @@ -0,0 +1,41 @@ +package net.nuclearteam.createnuclear.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import net.minecraft.ChatFormatting; +import net.nuclearteam.createnuclear.content.multiblock.IHeat; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; + +public class HeatDisplaySource extends AbstractReactorStatDisplaySource { + + @Override + protected String getLabelKey() { + return "display_source.reactor.heat"; + } + + @Override + protected int getMax() { + return ReactorDisplayConstants.MAX_HEAT; + } + + @Override + protected ChatFormatting getColor(int value, ReactorControllerBlockEntity controller) { + return IHeat.HeatLevel.of(value, controller.getMultiblockSize()).getTextColor(); + } + + /** + * Divergence assumee vs Forge : Forge lit + * {@code controller.getConfiguredPattern().getOrCreateTag().getDouble("heat")}. + * En 1.21 la chaleur vit dans le data component {@code CNDataComponents.HEAT} ; + * relire le tag NBT de la stack renvoie une copie defensive, donc la valeur y est + * toujours absente. On passe par l'accesseur dedie du controleur. + */ + @Override + protected int computeValue(ReactorControllerBlockEntity controller, DisplayLinkContext context) { + return controller.getConfiguredPatternHeat(); + } + + @Override + protected String getTranslationKey() { + return "heat"; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/LiquidLevelDisplaySource.java b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/LiquidLevelDisplaySource.java new file mode 100644 index 0000000..bbcb119 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/LiquidLevelDisplaySource.java @@ -0,0 +1,43 @@ +package net.nuclearteam.createnuclear.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.MutableComponent; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; + +import java.util.List; + +public class LiquidLevelDisplaySource extends AbstractReactorStatDisplaySource { + @Override + protected String getLabelKey() { + return "display_source.reactor.fluid"; + } + + @Override + protected int getMax() { + return ReactorDisplayConstants.MAX_FLUID; + } + + @Override + protected ChatFormatting getColor(int value, ReactorControllerBlockEntity controller) { + return ChatFormatting.BLUE; + } + + @Override + protected int computeValue(ReactorControllerBlockEntity controller, DisplayLinkContext context) { + List fluidList = controller.getBigFluidStack(); + return (fluidList != null && !fluidList.isEmpty()) ? fluidList.get(0).amount : 0; + } + + @Override + protected MutableComponent getUnitSuffix() { + return CreateNuclearLang.translateDirect("generic.unit.fluid.value"); + } + + @Override + protected String getTranslationKey() { + return "liquid_level"; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorDisplayConstants.java b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorDisplayConstants.java new file mode 100644 index 0000000..28360ff --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorDisplayConstants.java @@ -0,0 +1,9 @@ +package net.nuclearteam.createnuclear.content.redstone.displayLink.source; + +final class ReactorDisplayConstants { + static final int MAX_FUEL = 64; + static final int MAX_COOLER = 64; + static final int MAX_FLUID = 16000; + static final int MAX_HEAT = 1000; + private ReactorDisplayConstants() {} +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorGaugeRenderer.java b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorGaugeRenderer.java new file mode 100644 index 0000000..4b590b1 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorGaugeRenderer.java @@ -0,0 +1,15 @@ +package net.nuclearteam.createnuclear.content.redstone.displayLink.source; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.Mth; + +public final class ReactorGaugeRenderer { + private ReactorGaugeRenderer() {} + + static MutableComponent drawGauge(int current, int max, ChatFormatting color, int width) { + int filled = (int) (Mth.clamp((float) current / max, 0, 1) * width); + return Component.literal("█".repeat(filled) + "▒".repeat(Math.max(0, width - filled))).withStyle(color); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorSizeDisplaySource.java b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorSizeDisplaySource.java new file mode 100644 index 0000000..04faf4d --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorSizeDisplaySource.java @@ -0,0 +1,54 @@ +package net.nuclearteam.createnuclear.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.source.NumericSingleLineDisplaySource; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; + +public class ReactorSizeDisplaySource extends NumericSingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + ReactorControllerBlockEntity controller = MultiblockHelpers.getControllerForPart(context.level(), context.getSourcePos()); + if (controller == null || controller.isRemoved()) return ZERO.copy(); + + // Label + trailing space + MutableComponent label = CreateNuclearLang.translateDirect("display_source.reactor.size").append(" "); + + int mode = context.sourceConfig().getInt("display_mode"); + int size = controller.getMultiblockSize(); + int tier = size <= 5 ? 1 : size <= 7 ? 2 : 3; + + return label.append(switch (mode) { + case 1 -> Component.literal((tier * 100 / 3) + "%").withStyle(ChatFormatting.BLUE); + case 2 -> { + // Short 3-segment gauge representing the tier + yield Component.literal("█".repeat(tier) + "▒".repeat(3 - tier)).withStyle(ChatFormatting.BLUE); + } + default -> { + String key = tier == 1 ? "small" : tier == 2 ? "medium" : "large"; + yield CreateNuclearLang.translateDirect("display_source.reactor.size." + key).withStyle(ChatFormatting.BLUE); + } + }); + } + + @Override protected String getTranslationKey() { return "size"; } + + @Override + @OnlyIn(Dist.CLIENT) + public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) { + if (isFirstLine) return; + builder.addSelectionScrollInput(0, 100, (selectionScrollInput, l) -> selectionScrollInput + .forOptions(CreateNuclearLang.translatedOptions("display_source.reactor.mode", "value", "percent", "gauge")), "display_mode"); + } + + @Override protected boolean allowsLabeling(DisplayLinkContext context) { return true; } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorSummary.java b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorSummary.java new file mode 100644 index 0000000..8079520 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorSummary.java @@ -0,0 +1,106 @@ +package net.nuclearteam.createnuclear.content.redstone.displayLink.source; + +import net.minecraft.network.chat.MutableComponent; + +import java.util.ArrayList; +import java.util.List; + +/** + * Typed, immutable snapshot of a reactor controller's summary stats (status, size, + * fuel, cooler, fluid, heat), one named {@link ReactorSummaryRow} per stat. + *

+ * Replaces the previous {@code List>} representation, which + * relied on a size-based sentinel (1 element = no controller, 6 elements = full + * summary) and on fragile positional access (e.g. {@code components.get(2).get(1)} + * for the fuel value) that silently broke if the row order ever changed. + *

+ * Callers should build instances via {@link Builder}, and only call {@link #toRows()} + * at the point where Create's {@code DisplaySource} API actually requires the + * positional list format. + */ +public record ReactorSummary(ReactorSummaryRow status, + ReactorSummaryRow size, + ReactorSummaryRow fuel, + ReactorSummaryRow cooler, + ReactorSummaryRow fluid, + ReactorSummaryRow heat) { + + /** A single display row: a label component and its associated value component. */ + public record ReactorSummaryRow(MutableComponent label, MutableComponent value) { + List toPair() { + return List.of(label(), value()); + } + } + + /** + * Converts this summary to the positional {@code List>} + * format required by Create's {@code DisplaySource} API. This is the single place + * where row order matters; every other consumer should access fields by name + * (e.g. {@link #fuel()}) instead of relying on this order. + */ + public List> toRows() { + return List.of( + status().toPair(), size().toPair(), fuel().toPair(), + cooler().toPair(), fluid().toPair(), heat().toPair() + ); + } + + /** + * Fluent builder for {@link ReactorSummary}. All six rows are required; + * {@link #build()} throws {@link IllegalStateException} naming any missing row + * instead of allowing a partially-populated summary to be constructed silently. + */ + public static class Builder { + private ReactorSummaryRow status; + private ReactorSummaryRow size; + private ReactorSummaryRow fuel; + private ReactorSummaryRow cooler; + private ReactorSummaryRow fluid; + private ReactorSummaryRow heat; + + public Builder status(MutableComponent label, MutableComponent value) { + this.status = new ReactorSummaryRow(label, value); + return this; + } + + public Builder size(MutableComponent label, MutableComponent value) { + this.size = new ReactorSummaryRow(label, value); + return this; + } + + public Builder fuel(MutableComponent label, MutableComponent value) { + this.fuel = new ReactorSummaryRow(label, value); + return this; + } + + public Builder cooler(MutableComponent label, MutableComponent value) { + this.cooler = new ReactorSummaryRow(label, value); + return this; + } + + public Builder fluid(MutableComponent label, MutableComponent value) { + this.fluid = new ReactorSummaryRow(label, value); + return this; + } + + public Builder heat(MutableComponent label, MutableComponent value) { + this.heat = new ReactorSummaryRow(label, value); + return this; + } + + public ReactorSummary build() { + List missing = new ArrayList<>(); + if (status == null) missing.add("status"); + if (size == null) missing.add("size"); + if (fuel == null) missing.add("fuel"); + if (cooler == null) missing.add("cooler"); + if (fluid == null) missing.add("fluid"); + if (heat == null) missing.add("heat"); + + if (!missing.isEmpty()) + throw new IllegalStateException("Missing required ReactorSummary fields: " + String.join(", ", missing)); + + return new ReactorSummary(status, size, fuel, cooler, fluid, heat); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorSummaryDisplaySource.java b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorSummaryDisplaySource.java new file mode 100644 index 0000000..e61340c --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/redstone/displayLink/source/ReactorSummaryDisplaySource.java @@ -0,0 +1,243 @@ +package net.nuclearteam.createnuclear.content.redstone.displayLink.source; + +import com.simibubi.create.api.behaviour.display.DisplaySource; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayLayout; +import com.simibubi.create.content.trains.display.FlapDisplaySection; +import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; +import net.minecraft.ChatFormatting; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.level.block.entity.LecternBlockEntity; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType.TypeRodPredicate; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.IHeat; +import net.nuclearteam.createnuclear.content.multiblock.MultiblockHelpers; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; + +/** + * Display source rendering a reactor controller's summary (status, size, fuel, + * cooler, fluid, heat) as one line per stat, for both regular displays and + * flap displays. + *

+ * The underlying data is built by {@link #getReactorSummary} into a + * {@link ReactorSummary}, which is only converted to Create's positional + * {@code List>} format at the last moment via + * {@link ReactorSummary#toRows()}, right before returning it to the caller. + */ +public class ReactorSummaryDisplaySource extends DisplaySource { + + /** Fallback line shown when only a single display row is available. */ + public static final List notEnoughSpaceSingle = + List.of(CreateNuclearLang.translateDirect("display_source.reactor.not_enough_space") + .append(CreateNuclearLang.translateDirect("display_source.reactor.for_reactor_status"))); + + /** Fallback lines shown when fewer than 6 rows are available (not enough for the full summary). */ + public static final List notEnoughSpaceDouble = + List.of(CreateNuclearLang.translateDirect("display_source.reactor.not_enough_space"), + CreateNuclearLang.translateDirect("display_source.reactor.for_reactor_status")); + + /** Fallback flap display rows, mirroring {@link #notEnoughSpaceDouble} for the flap layout. */ + public static final List> notEnoughSpaceFlap = + List.of(List.of(CreateNuclearLang.translateDirect("display_source.reactor.not_enough_space")), + List.of(CreateNuclearLang.translateDirect("display_source.reactor.for_reactor_status"))); + + /** + * Provides the text lines for a regular (non-flap) display target. + * Falls back to {@link #notEnoughSpaceSingle}/{@link #notEnoughSpaceDouble} when there + * isn't enough room, and to the "no controller" message when no reactor controller + * could be resolved for this source. + */ + @Override + public List provideText(DisplayLinkContext context, DisplayTargetStats stats) { + if (stats.maxRows() < 2) return notEnoughSpaceSingle; + if (stats.maxRows() < 6) return notEnoughSpaceDouble; + + int gaugeWidth = (stats.maxColumns() >= 80) ? 10 : 6; + + Optional summary = getReactorSummary(context, gaugeWidth); + if (summary.isEmpty()) { + return List.of(CreateNuclearLang.translateDirect("display_source.reactor.no_controller")); + } + + List> components = summary.get().toRows(); + + if (context.getTargetBlockEntity() instanceof LecternBlockEntity) { + Stream componentList = components.stream().map(list -> list.stream().reduce(MutableComponent::append).orElse(EMPTY_LINE)); + return List.of(componentList.reduce((c1, c2) -> c1.append(Component.literal("\n")).append(c2)).orElse(EMPTY_LINE)); + } + + return components.stream().map(list -> list.stream().reduce(MutableComponent::append).orElse(EMPTY_LINE)).toList(); + } + + /** + * Provides the rows for a flap display target. Disables the flap display context + * (falls back to the default layout) when there isn't enough room, either because + * of the row count or because the fuel value wouldn't fit the available columns. + */ + @Override + public List> provideFlapDisplayText(DisplayLinkContext context, DisplayTargetStats stats) { + if (stats.maxRows() < 6) { + context.flapDisplayContext = Boolean.FALSE; + return notEnoughSpaceFlap; + } + + int gaugeWidth = 6; + Optional summary = getReactorSummary(context, gaugeWidth); + + if (summary.isEmpty()) { + return notEnoughSpaceFlap; + } + + ReactorSummary reactorSummary = summary.get(); + + if (stats.maxColumns() * FlapDisplaySection.MONOSPACE < 6 * FlapDisplaySection.MONOSPACE + reactorSummary.fuel() + .value().getString().length() * FlapDisplaySection.WIDE_MONOSPACE) { + context.flapDisplayContext = Boolean.FALSE; + return notEnoughSpaceFlap; + } + + return reactorSummary.toRows(); + } + + /** + * Configures the flap display layout: the default layout for the first line + * (or when the flap display context was disabled by {@link #provideFlapDisplayText}), + * otherwise a two-section "Reactor" layout (label column + value/gauge column). + */ + @Override + public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, FlapDisplayLayout layout, int lineIndex) { + if (lineIndex == 0 || context.flapDisplayContext instanceof Boolean b && !b) { + if (layout.isLayout("Default")) return; + layout.loadDefault(flapDisplay.getMaxCharCount()); + return; + } + + String layoutKey = "Reactor"; + if (layout.isLayout(layoutKey)) return; + + int lw = labelWidth(); + int labelLength = (int) (lw * FlapDisplaySection.MONOSPACE); + float maxSpace = flapDisplay.getMaxCharCount(1) * FlapDisplaySection.MONOSPACE; + + FlapDisplaySection label = new FlapDisplaySection(labelLength, "alphabet", false, true); + FlapDisplaySection symbols = new FlapDisplaySection(maxSpace - labelLength, "pixel", false, false).wideFlaps(); + + layout.configure(layoutKey, List.of(label, symbols)); + } + + /** + * Resolves the reactor controller for this source and builds a {@link ReactorSummary} + * from its current state. Returns {@link Optional#empty()} when no controller is + * assigned to this display source or it has been removed, so callers can distinguish + * that case from a valid summary without relying on list size/positional access. + */ + private Optional getReactorSummary(DisplayLinkContext context, int gaugeWidth) { + ReactorControllerBlockEntity controller = MultiblockHelpers.getControllerForPart(context.level(), context.getSourcePos()); + + if (controller == null || controller.isRemoved()) { + return Optional.empty(); + } + + int mode = context.sourceConfig().getInt("display_mode"); + + // Divergence assumee vs Forge, qui lit getConfiguredPattern().getOrCreateTag().getDouble("heat") : + // en 1.21 la chaleur vit dans le data component CNDataComponents.HEAT, et relire le tag NBT de la + // stack renvoie une copie defensive ou la valeur est toujours absente (elle valait donc 0 ici). + int heat = controller.getConfiguredPatternHeat(); + int fuel = 0; + int cooler = 0; + + if (controller.getDisplayState() != null && controller.getDisplayState().items() != null) { + for (Map.Entry entry : controller.getDisplayState().items().entrySet()) { + if (TypeRodPredicate.isFuel(entry.getKey().getDefaultInstance(), context.level())) { + fuel += entry.getValue(); + } else if (TypeRodPredicate.isCooled(entry.getKey().getDefaultInstance(), context.level())) { + cooler += entry.getValue(); + } + } + } + + int size = controller.getMultiblockSize(); + List fluidList = controller.getBigFluidStack(); + int fluid = (fluidList != null && !fluidList.isEmpty() && fluidList.get(0) != null) ? fluidList.get(0).amount : 0; + + int lw = labelWidth(); + MutableComponent lStatus = padLabel("status", lw).append(" "); + MutableComponent lSize = padLabel("size", lw).append(" "); + MutableComponent lFuel = padLabel("fuel", lw).append(" "); + MutableComponent lCooler = padLabel("cooler", lw).append(" "); + MutableComponent lFluid = padLabel("fluid", lw).append(" "); + MutableComponent lHeat = padLabel("heat", lw).append(" "); + + return Optional.of(new ReactorSummary.Builder() + .status(lStatus, controller.isAssembled() ? + CreateNuclearLang.translateDirect("display_source.reactor.active").withStyle(ChatFormatting.GOLD) : + CreateNuclearLang.translateDirect("display_source.reactor.idle").withStyle(ChatFormatting.GRAY)) + .size(lSize, formatSize(size)) + .fuel(lFuel, formatValue(fuel, ReactorDisplayConstants.MAX_FUEL, mode, false, ChatFormatting.GREEN, gaugeWidth)) + .cooler(lCooler, formatValue(cooler, ReactorDisplayConstants.MAX_COOLER, mode, false, ChatFormatting.AQUA, gaugeWidth)) + .fluid(lFluid, formatFluid(fluid, ReactorDisplayConstants.MAX_FLUID, mode, ChatFormatting.BLUE, gaugeWidth)) + .heat(lHeat, formatValue(heat, ReactorDisplayConstants.MAX_HEAT, mode, true, IHeat.HeatLevel.of(heat, controller.getMultiblockSize()).getTextColor(), gaugeWidth)) + .build()); + } + + private MutableComponent padLabel(String key, int lw) { + return Component.literal(" ".repeat(lw - labelWidthOf(key))).append(labelOf(key)); + } + + private MutableComponent formatSize(int size) { + String key = size <= 5 ? "small" : size <= 7 ? "medium" : "large"; + return CreateNuclearLang.translateDirect("display_source.reactor.size." + key).withStyle(ChatFormatting.BLUE); + } + + private MutableComponent formatFluid(int current, int max, int mode, ChatFormatting color, int width) { + if (mode == 0 || mode == 3) return ReactorGaugeRenderer.drawGauge(current, max, color, width); + if (mode == 2) return Component.literal((current * 100 / max) + "%").withStyle(color); + return Component.literal(String.valueOf(current)).append(" ").append(CreateNuclearLang.translateDirect("generic.unit.fluid.value")).withStyle(color); + } + + private MutableComponent formatValue(int current, int max, int mode, boolean gaugeOnNormal, ChatFormatting color, int width) { + if (mode == 3 || (mode == 0 && gaugeOnNormal)) return ReactorGaugeRenderer.drawGauge(current, max, color, width); + if (mode == 2) return Component.literal((current * 100 / max) + "%").withStyle(color); + return Component.literal(String.valueOf(current)).withStyle(color); + } + + private int labelWidth() { + return Stream.of("status", "size", "fuel", "cooler", "fluid", "heat").mapToInt(this::labelWidthOf).max().orElse(0); + } + + private int labelWidthOf(String label) { + return labelOf(label).getString().length(); + } + + private MutableComponent labelOf(String label) { + return CreateNuclearLang.translateDirect("display_source.reactor." + label); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, boolean isFirstLine) { + if (isFirstLine) return; + builder.addSelectionScrollInput(0, 100, (selectionScrollInput, label) -> selectionScrollInput + .forOptions(CreateNuclearLang.translatedOptions("display_source.reactor.mode", "normal", "value", "percent", "gauge")), "display_mode"); + } + + @Override + protected String getTranslationKey() { + return "reactor_summary"; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/uraniumOre/UraniumOreItem.java b/src/main/java/net/nuclearteam/createnuclear/content/uraniumOre/UraniumOreItem.java new file mode 100644 index 0000000..5169bcb --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/uraniumOre/UraniumOreItem.java @@ -0,0 +1,21 @@ +package net.nuclearteam.createnuclear.content.uraniumOre; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.nuclearteam.createnuclear.api.radiation.IRadiationSource; + +public class UraniumOreItem extends BlockItem implements IRadiationSource { + private final double radiation; + + public UraniumOreItem(Block block, Properties properties, double radiation) { + super(block, properties); + this.radiation = radiation; + } + + @Override + public double getRadiation(ItemStack stack, LivingEntity entity) { + return this.radiation * stack.getCount(); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNAdvancement.java b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNAdvancement.java index 5ff725a..3ffe713 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNAdvancement.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNAdvancement.java @@ -5,38 +5,51 @@ import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.AdvancementHolder; +import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.advancements.critereon.*; import net.minecraft.core.HolderLookup; import net.minecraft.data.CachedOutput; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.DyeColor; -import net.nuclearteam.createnuclear.CNBlocks; -import net.nuclearteam.createnuclear.CNFluids; -import net.nuclearteam.createnuclear.CNItems; -import net.nuclearteam.createnuclear.CNTags; +import net.minecraft.tags.ItemTags; +import net.minecraft.world.entity.EntityType; +import net.neoforged.neoforge.common.Tags; +import net.nuclearteam.createnuclear.*; +import net.nuclearteam.createnuclear.content.decoration.palettes.CNPaletteStoneTypes; import net.nuclearteam.createnuclear.foundation.advancement.CreateNuclearAdvancement.Builder; - import javax.annotation.ParametersAreNonnullByDefault; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.UnaryOperator; - -import static net.nuclearteam.createnuclear.foundation.advancement.CreateNuclearAdvancement.TaskType.SILENT; -import static net.nuclearteam.createnuclear.foundation.advancement.CreateNuclearAdvancement.TaskType.SECRET; +import static net.nuclearteam.createnuclear.foundation.advancement.CreateNuclearAdvancement.TaskType.*; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault @SuppressWarnings("unused") public class CNAdvancement implements DataProvider { + public static final EntityEquipmentPredicate FULL_ARMOR = new EntityEquipmentPredicate.Builder() + .head(ItemPredicate.Builder.item().of(CNItems.ANTI_RADIATION_HELMETS)) + .chest(ItemPredicate.Builder.item().of(CNItems.ANTI_RADIATION_CHESTPLATES)) + .legs(ItemPredicate.Builder.item().of(CNItems.ANTI_RADIATION_LEGGINGS)) + .feet(ItemPredicate.Builder.item().of(CNItems.ANTI_RADIATION_BOOTS)) + .build(); + + private static final List PREDICATES = List.of( + ItemPredicate.Builder.item().of(CNBlocks.ENRICHED_SOUL_SOIL), + ItemPredicate.Builder.item().of(ItemTags.LOGS), + ItemPredicate.Builder.item().of(Tags.Items.RODS_WOODEN) + ); + public static final List ENTRIES = new ArrayList<>(); public static final CreateNuclearAdvancement START = null, @@ -44,176 +57,321 @@ public class CNAdvancement implements DataProvider { .title("Starting The Nuclear Journey") .description("Unlock the basics of nuclear energy and get your first uranium powder") .awardedForFree() - .special(SILENT)), + .special(SILENT) + ), + + CRAFT_ENRICHING_CAMPFIRE = create("craft_enriching_campfire", b -> b.icon(CNBlocks.ENRICHING_CAMPFIRE.asItem()) + .title("Does That Make Smoke?") + .description("Craft an Enriching Campfire") + .externalTrigger(RecipeCraftedTrigger.TriggerInstance.craftedItem(CreateNuclear.asResource("crafting/enriching_campfire"), PREDICATES)) + .after(ROOT) + ), RAW_URANIUM = create("raw_uranium", b -> b.icon(CNItems.RAW_URANIUM) .title("The Raw Power") .description("Mine uranium ore to obtain raw uranium for further processing") .after(ROOT) - .whenIconCollected()), + .whenIconCollected() + ), URANIUM_POWDER = create("uranium_powder", b -> b.icon(CNItems.URANIUM_POWDER) .title("Powdered Uranium") .description("Crush raw uranium into powder to prepare for further refining") .after(RAW_URANIUM) - .whenIconCollected()), + .whenIconCollected() + ), + + AUTOMATIC_URANIUM = create("automatic_uranium", b -> b.icon(CNItems.URANIUM_POWDER) + .title("Automating Uranium") + .description("Obtain some uranium powder using the automatic uranium processing") + .after(ROOT) + .special(SECRET) + ), URANIUM_LIQUID = create("uranium_liquid", b -> b.icon(CNFluids.URANIUM.getBucket().get()) .title("Turning Solid To Liquid") .description("Obtain some uranium liquid by mixing uranium powder") .after(URANIUM_POWDER) - .whenIconCollected()), + .whenIconCollected() + ), YELLOWCAKE = create("yellowcake", b -> b.icon(CNItems.YELLOWCAKE) .title("The Yellowcake Process") .description("Compact uranium liquid to create yellowcake") .after(URANIUM_LIQUID) - .whenIconCollected()), + .whenIconCollected() + ), + + CRUNCHY_URANIUM = create("crunchy_uranium", b -> b.icon(CNItems.YELLOWCAKE) + .title("What Did You Expect") + .description("Bro..... you did what ??") + .after(YELLOWCAKE) + .externalTrigger(ConsumeItemTrigger.TriggerInstance.usedItem(CNItems.YELLOWCAKE)) + .special(SECRET) + ), ENRICHED_YELLOWCAKE = create("enriched_yellowcake", b -> b.icon(CNItems.ENRICHED_YELLOWCAKE) .title("Enhancing Yellowcake") .description("Use a fan to enrich yellowcake and make it more powerful") .after(YELLOWCAKE) - .whenIconCollected()), + .whenIconCollected() + ), URANIUM_ROD = create("uranium_rod", b -> b.icon(CNItems.URANIUM_ROD) .title("The Power Of The Atom") .description("Create your first uranium rod using enriched yellowcake in a mechanical crafter") .after(ENRICHED_YELLOWCAKE) - .whenIconCollected()), + .whenIconCollected() + ), + RAW_THORIUM = create("raw_thorium", b -> b.icon(CNItems.RAW_THORIUM) + .title("Thorium's Glow") + .description("Mine thorium ore to obtain raw thorium for further processing") + .after(ROOT) + .whenIconCollected() + ), + + THORIUM_DUST = create("thorium_dust", b -> b.icon(CNItems.THORIUM_DUST) + .title("Powdered Thorium") + .description("Crush raw thorium into dust to prepare for further refining") + .after(RAW_THORIUM) + .whenIconCollected() + ), + + THORIUM_LIQUID = create("thorium_liquid", b -> b.icon(CNFluids.THORIUM.getBucket().get()) + .title("Molten Thorium") + .description("Obtain some thorium liquid by mixing thorium dust") + .after(THORIUM_DUST) + .whenIconCollected() + ), + + THORIUM_INGOT = create("thorium_ingot", b -> b.icon(CNItems.THORIUM_INGOT) + .title("Compacted Thorium") + .description("Compact thorium liquid to create a thorium ingot") + .after(THORIUM_LIQUID) + .whenIconCollected() + ), + + THORIUM_ROD = create("thorium_rod", b -> b.icon(CNItems.THORIUM_ROD) + .title("What A Blue Stick") + .description("Craft a thorium rod for the first time") + .after(THORIUM_INGOT) + .whenIconCollected() + ), + + CHEMISTRY_101 = create("chemistry_101", b -> b.icon(CNItems.NITRATE) + .title("Crushing It") + .description("Mine nitrate ore or crush limestone to obtain nitrate") + .after(ROOT) + .whenIconCollected() + ), + + GETTING_CONCENTRATED = create("getting_concentrated", b -> b.icon(CNItems.NITROGEN_CONCENTRATE) + .title("Getting Concentrated") + .description("Smelt nitrate in a blast furnace to obtain nitrogen concentrate") + .after(CHEMISTRY_101) + .whenIconCollected() + ), + + CHILL_OUT = create("chill_out", b -> b.icon(CNItems.COOLED_NITROGEN_CONCENTRATE) + .title("Chill Out") + .description("Cool down nitrogen concentrate to prepare it for liquefaction") + .after(GETTING_CONCENTRATED) + .whenIconCollected() + ), + + ABSOLUTE_ZERO = create("absolute_zero", b -> b.icon(CNFluids.LIQUID_NITROGEN.getBucket().get()) + .title("Absolute Zero") + .description("Mix cooled nitrogen concentrate to obtain liquid nitrogen") + .after(CHILL_OUT) + .whenIconCollected() + ), + + CRYOGENIC_BAPTISM = create("cryogenic_baptism", b -> b.icon(CNFluids.LIQUID_NITROGEN.getBucket().get()) + .title("I can't Feel My Feet Anymore") + .description("Swim in the liquid nitrogen for the first time") + .after(ABSOLUTE_ZERO) + .special(SECRET) + ), COAL_DUST = create("coal_dust", b -> b.icon(CNItems.COAL_DUST) .title("Coal Dust") .description("Crush coal or charcoal to obtain coal dust, a key crafting material") .after(ROOT) - .whenIconCollected()), + .whenIconCollected() + ), STEEL_INGOT = create("steel_ingot", b -> b.icon(CNItems.STEEL_INGOT) .title("Steel Ingot") .description("Combine coal dust and iron ingots to create steel ingots") .after(COAL_DUST) - .whenIconCollected()), + .whenIconCollected() + ), GRAPHENE = create("graphene", b -> b.icon(CNItems.GRAPHENE) .title("Graphene") .description("Press coal dust to create graphene") .after(COAL_DUST) - .whenIconCollected()), + .whenIconCollected() + ), GRAPHITE_ROD = create("graphite_rod", b -> b.icon(CNItems.GRAPHITE_ROD) .title("Don't Forget Those Ones") .description("Combine graphene and steel ingots in a mechanical crafter to make graphite rods") .after(GRAPHENE) - .whenIconCollected()), - + .whenIconCollected() + ), RAW_LEAD = create("raw_lead", b -> b.icon(CNItems.RAW_LEAD) .title("Raw Lead") .description("Obtain some raw lead by mining lead ore") .after(ROOT) - .whenIconCollected()), + .whenIconCollected() + ), LEAD_INGOT = create("lead_ingot", b -> b.icon(CNItems.LEAD_INGOT) - .title("Lead ingot") + .title("Lead Ingot") .description("Smelt a raw lead to obtain a lead ingot") .after(RAW_LEAD) - .whenIconCollected()), + .whenIconCollected() + ), REINFORCED_GLASS = create("reinforced_glass", b -> b.icon(CNBlocks.REINFORCED_GLASS) .title("Reinforced Glass") .description("Craft some reinforced glass for the first time") .after(LEAD_INGOT) - .whenIconCollected()), + .whenIconCollected() + ), - ANTI_RADIATION_ARMOR = create("anti_radiation_armor", b -> b.icon(CNItems.ANTI_RADIATION_HELMETS.get(DyeColor.WHITE)) - .title("Anti radiation Armor") + ANTI_RADIATION_ARMOR = create("anti_radiation_armor", b -> b.icon(CNItems.ANTI_RADIATION_HELMETS) + .title("Anti Radiation Armor") .description("Craft your first anti-radiation armor piece to protect yourself from radiation") .after(LEAD_INGOT) - .whenItemCollected(CNTags.CNItemTags.ALL_ANTI_RADIATION_ARMORS.tag)), - - FULL_ANTI_RADIATION_ARMOR = create("full_anti_radiation_armor", b -> b.icon(CNItems.ANTI_RADIATION_CHESTPLATES.get(DyeColor.WHITE)) - .title("Fully Protected") - .description("Wear a full set of anti-radiation armor to fully protect yourself from radiation") - //.externalTrigger( - // InventoryChangeTrigger.TriggerInstance.hasItems( - // new ItemPredicate(CNTags.CNItemTags.ANTI_RADIATION_HELMET_FULL_DYE.tag, null, MinMaxBounds.Ints.ANY, MinMaxBounds.Ints.ANY, null, null, null, NbtPredicate.ANY), - // new ItemPredicate(CNTags.CNItemTags.ANTI_RADIATION_CHESTPLATE_FULL_DYE.tag, null, MinMaxBounds.Ints.ANY, MinMaxBounds.Ints.ANY, null, null, null, NbtPredicate.ANY), - // new ItemPredicate(CNTags.CNItemTags.ANTI_RADIATION_LEGGINGS_FULL_DYE.tag, null, MinMaxBounds.Ints.ANY, MinMaxBounds.Ints.ANY, null, null, null, NbtPredicate.ANY), - // new ItemPredicate(CNTags.CNItemTags.ANTI_RADIATION_BOOTS_DYE.tag, null, MinMaxBounds.Ints.ANY, MinMaxBounds.Ints.ANY, null, null, null, null) - // )) - .after(ANTI_RADIATION_ARMOR)), - - DYE_ANTI_RADIATION_ARMOR = create("dye_anti_radiation_armor", b -> b.icon(CNItems.ANTI_RADIATION_HELMETS.get(DyeColor.RED)) + .whenItemCollected(CNTags.CNItemTags.ANTI_RADIATION_ARMOR.tag) + ), + + AVOIDING_CANCER = create("avoiding_cancer", b -> b.icon(CNItems.ANTI_RADIATION_HELMETS) + .title("Best Keep Yourself Covered") + .description("Equip anti-radiation armor for the first time") + .after(ANTI_RADIATION_ARMOR) + .externalTrigger( + CriteriaTriggers.INVENTORY_CHANGED.createCriterion( + new InventoryChangeTrigger.TriggerInstance( + Optional.of(EntityPredicate.wrap(EntityPredicate.Builder.entity().of(EntityType.PLAYER).equipment(FULL_ARMOR).build())), + InventoryChangeTrigger.TriggerInstance.Slots.ANY, + List.of() + ) + ) + ) + ), + + DYE_ANTI_RADIATION_ARMOR = create("dye_anti_radiation_armor", b -> b.icon(CNItems.ANTI_RADIATION_HELMETS) .title("Pimp My Armor") .description("Dye your anti radiation armor to any color") - .whenItemCollected(CNTags.CNItemTags.ANTI_RADIATION_HELMET_DYE.tag) - .whenItemCollected(CNTags.CNItemTags.ANTI_RADIATION_CHESTPLATE_DYE.tag) - .whenItemCollected(CNTags.CNItemTags.ANTI_RADIATION_LEGGINGS_DYE.tag) - .after(ANTI_RADIATION_ARMOR)), - - - AUTOMATIC_URANIUM = create("automatic_uranium", b -> b.icon(CNItems.URANIUM_POWDER) - .title("Automating Uranium") - .description("Obtain some uranium powder using the automatic uranium processing") - .after(ROOT) - .special(SECRET)), + .after(ANTI_RADIATION_ARMOR) + ), REACTOR_CASING = create("reactor_casing", b -> b.icon(CNBlocks.REACTOR_CASING) .title("The Power Of The Reactor") .description("Craft a reactor casing to begin building your nuclear reactor") .after(ROOT) - .whenIconCollected()), + .whenIconCollected() + ), + + SILENCE_THE_CORE = create("silence_the_core", b -> b.icon(CNBlocks.REACTOR_ALARM.asItem()) + .title("It Makes So Much Noise !") + .description("sound the alarm for the first time") + .after(REACTOR_CASING) + ), REACTOR_CONTROLLER = create("reactor_controller", b -> b.icon(CNBlocks.REACTOR_CONTROLLER) .title("Controller Of The Core") .description("Craft a reactor controller to manage and regulate your reactor") .after(REACTOR_CASING) - .whenIconCollected()), + .whenIconCollected() + ), + NO_TIME_TO_DIE = create("no_time_to_die", b -> b.icon(CNPaletteStoneTypes.AUTUNITE.baseBlock.get().asItem()) + .title("No Time To Die") + .description("Stop the reactor before the KABOOOM !") + .after(REACTOR_CONTROLLER) + ), + + T1_REACTOR = create("t1", b -> b.icon(CNBlocks.REACTOR_CONTROLLER.asItem()) + .title("Reactor Controller T1") + .description("Build a tier 1 Nuclear Reactor") + .special(EXPERT) + .after(REACTOR_CONTROLLER) + ), + + T2_REACTOR = create("t2", b -> b.icon(CNBlocks.REACTOR_CONTROLLER.asItem()) + .title("Reactor Controller T2") + .description("Build a tier 2 Nuclear Reactor") + .special(EXPERT) + .after(T1_REACTOR) + ), + + T3_REACTOR = create("t3", b -> b.icon(CNBlocks.REACTOR_CONTROLLER.asItem()) + .title("Reactor Controller T3") + .description("Build a tier 3 Nuclear Reactor") + .special(EXPERT) + .after(T2_REACTOR) + ), REACTOR_BLUEPRINT = create("reactor_blueprint", b -> b.icon(CNItems.REACTOR_BLUEPRINT) .title("Blueprint For Power") .description("Craft a reactor blueprint to design the layout of rods in your reactor") .after(REACTOR_CONTROLLER) - .whenIconCollected()), + .whenIconCollected() + ), - REACTOR_COOLER = create("reactor_cooler", b -> b.icon(CNBlocks.REACTOR_COOLER) - .title("Cooling The Reactor") - .description("Craft a reactor cooler to cool your reactor") + REACTOR_ROD_INPUT = create("feeding_the_reactor", b -> b.icon(CNBlocks.REACTOR_ROD_INPUT) + .title("Feeding The Reactor") + .description("Craft a Reactor Rod Input to feed heating and cooling rods into your reactor") .after(REACTOR_CASING) - .whenIconCollected()), + .whenIconCollected() + ), - REACTOR_FRAME = create("reactor_frame", b -> b.icon(CNBlocks.REACTOR_FRAME) - .title("Reactor Frame") - .description("Craft a reactor frame to build your nuclear reactor") - .after(REACTOR_CASING) - .whenIconCollected()), - - REACTOR_INPUT = create("reactor_input", b -> b.icon(CNBlocks.REACTOR_INPUT) + REACTOR_FLUID_INPUT = create("fueling_the_reactor", b -> b.icon(CNBlocks.REACTOR_FLUID_INPUT) .title("Fueling The Reactor") - .description("Craft a reactor input to feed uranium and graphite rods into your reactor") - .after(REACTOR_CASING) - .whenIconCollected()), - - REACTOR_OUTPUT = create("reactor_output", b -> b.icon(CNBlocks.REACTOR_OUTPUT) - .title("Power Output") - .description("Craft a reactor output to transfer the energy produced by your reactor") - .after(REACTOR_CASING) - .whenIconCollected()), + .description("Craft a Reactor Fluid Input to feed liquid coolant into your reactor") + .after(REACTOR_ROD_INPUT) + .whenIconCollected() + ), + + REACTOR_OUTPUT = create("unlimited_power", b -> b.icon(CNBlocks.REACTOR_OUTPUT) + .title("Unlimited Power") + .description("Craft a Reactor Output to extract the energy produced by your reactor") + .after(REACTOR_FLUID_INPUT) + .whenIconCollected() + ), REACTOR_CORE = create("reactor_core", b -> b.icon(CNBlocks.REACTOR_CORE) - .title("Core of Power") + .title("Core Of Power") .description("Craft the reactor core to harness the full energy of your nuclear reactor") .after(REACTOR_CASING) - .whenIconCollected()), + .whenIconCollected() + ), - END = null; + REACTOR_COOLER = create("reactor_cooler", b -> b.icon(CNBlocks.REACTOR_COOLER) + .title("Cooling The Reactor") + .description("Craft a reactor cooler to cool your reactor") + .after(REACTOR_CORE) + .whenIconCollected() + ), + + REACTOR_FRAME = create("reactor_frame", b -> b.icon(CNBlocks.REACTOR_FRAME) + .title("Reactor Frame") + .description("Craft a reactor frame to build your nuclear reactor") + .after(REACTOR_COOLER) + .whenIconCollected() + ) + + ; private final PackOutput output; private final CompletableFuture registries; - private static CreateNuclearAdvancement create(String id, UnaryOperator b) { return new CreateNuclearAdvancement(id, b); } @@ -228,14 +386,13 @@ public CompletableFuture run(CachedOutput cache) { return this.registries.thenCompose(provider -> { PackOutput.PathProvider pathProvider = output.createPathProvider(PackOutput.Target.DATA_PACK, "advancement"); List> futures = new ArrayList<>(); - Set set = Sets.newHashSet(); + Consumer consumer = (advancement) -> { ResourceLocation id = advancement.id(); if (!set.add(id)) throw new IllegalStateException("Duplicate advancement " + id); Path path = pathProvider.json(id); - LOGGER.info("Saving advancement {}", id); futures.add(DataProvider.saveStable(cache, provider, Advancement.CODEC, advancement.value(), path)); }; @@ -248,7 +405,7 @@ public CompletableFuture run(CachedOutput cache) { @Override public String getName() { - return "CreateNuclear's Advancements"; + return "Create Nuclear Advancements"; } public static void provideLang(BiConsumer consumer) { @@ -256,7 +413,5 @@ public static void provideLang(BiConsumer consumer) { advancement.provideLang(consumer); } - public static void register() { - } - -} \ No newline at end of file + public static void register() {} +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNAdvancementBehaviour.java b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNAdvancementBehaviour.java new file mode 100644 index 0000000..0c2a4ba --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNAdvancementBehaviour.java @@ -0,0 +1,128 @@ +package net.nuclearteam.createnuclear.foundation.advancement; + +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.advancement.CreateAdvancement; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.neoforged.neoforge.common.util.FakePlayer; + +import java.util.*; + +public class CNAdvancementBehaviour extends BlockEntityBehaviour { + public static final BehaviourType TYPE = new BehaviourType<>(); + + private UUID playerId; + private final Set advancements; + + public CNAdvancementBehaviour(SmartBlockEntity be, CreateNuclearAdvancement ...advancement) { + super(be); + this.advancements = new HashSet<>(); + add(advancement); + } + + public void add(CreateNuclearAdvancement ...advancement) { + Collections.addAll(this.advancements, advancement); + } + + public boolean isOwnerPresent() { + return playerId != null; + } + + public void setPlayer(UUID id) { + Player player = getWorld().getPlayerByUUID(id); + if (player == null) return; + playerId = id; + removeAwarded(); + blockEntity.setChanged(); + } + + @Override + public void initialize() { + super.initialize(); + removeAwarded(); + } + + private void removeAwarded() { + Player player = getPlayer(); + if (player == null) return; + + advancements.removeIf(c -> c.isAlreadyAwardedTo(player)); + if (advancements.isEmpty()) { + playerId = null; + blockEntity.setChanged(); + } + } + + public void awardPlayerIfNear(CreateNuclearAdvancement advancement, int maxDistance) { + Player player = getPlayer(); + if (player == null) + return; + if (player.distanceToSqr(Vec3.atCenterOf(getPos())) > maxDistance * maxDistance) + return; + award(advancement, player); + } + + public void awardPlayer(CreateNuclearAdvancement advancement) { + Player player = getPlayer(); + if (player == null) + return; + award(advancement, player); + } + + private void award(CreateNuclearAdvancement advancement, Player player) { + if (!advancements.contains(advancement)) advancement.awardTo(player); + removeAwarded(); + } + + private Player getPlayer() { + if (playerId == null) return null; + return getWorld().getPlayerByUUID(playerId); + } + + @Override + public void write(CompoundTag nbt, HolderLookup.Provider registries, boolean clientPacket) { + super.write(nbt, registries, clientPacket); + + if (playerId != null) + nbt.putUUID("Owner", playerId); + } + + @Override + public void read(CompoundTag nbt, HolderLookup.Provider registries, boolean clientPacket) { + super.read(nbt, registries, clientPacket); + + if (nbt.contains("Owner")) + playerId = nbt.getUUID("Owner"); + } + + public static void tryAward(BlockGetter reader, BlockPos pos, CreateAdvancement advancement) { + AdvancementBehaviour behaviour = BlockEntityBehaviour.get(reader, pos, AdvancementBehaviour.TYPE); + if (behaviour != null) + behaviour.awardPlayer(advancement); + } + + @Override + public BehaviourType getType() { + return TYPE; + } + + public static void setPlacedBy(Level worldIn, BlockPos pos, LivingEntity placer) { + CNAdvancementBehaviour behaviour = BlockEntityBehaviour.get(worldIn, pos, TYPE); + if (behaviour == null) + return; + if (placer instanceof FakePlayer) + return; + if (placer instanceof ServerPlayer) + behaviour.setPlayer(placer.getUUID()); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNTriggers.java b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNTriggers.java index fe30a57..9f256ff 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNTriggers.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CNTriggers.java @@ -1,7 +1,5 @@ package net.nuclearteam.createnuclear.foundation.advancement; -import com.simibubi.create.foundation.advancement.CriterionTriggerBase; -import com.simibubi.create.foundation.advancement.SimpleCreateTrigger; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; @@ -11,18 +9,19 @@ public class CNTriggers { private static final List> triggers = new LinkedList<>(); - public static SimpleCreateTrigger addSimple(String id) { - return add(new SimpleCreateTrigger(id)); + public static SimpleCreateNuclearTrigger addSimple(String id) { + return add(new SimpleCreateNuclearTrigger(id)); } private static > T add(T instance) { triggers.add(instance); + return instance; } public static void register() { - triggers.forEach(trigger -> { - Registry.register(BuiltInRegistries.TRIGGER_TYPES, trigger.getId(), trigger); + triggers.forEach(triggers -> { + Registry.register(BuiltInRegistries.TRIGGER_TYPES, triggers.getId(), triggers); }); } -} +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CreateNuclearAdvancement.java b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CreateNuclearAdvancement.java index 87383d9..afd1f76 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CreateNuclearAdvancement.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CreateNuclearAdvancement.java @@ -1,12 +1,11 @@ package net.nuclearteam.createnuclear.foundation.advancement; -import com.simibubi.create.Create; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.CreateAdvancement; -import com.simibubi.create.foundation.advancement.SimpleCreateTrigger; import com.tterrag.registrate.util.entry.ItemProviderEntry; -import net.minecraft.advancements.*; +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementHolder; +import net.minecraft.advancements.AdvancementType; +import net.minecraft.advancements.Criterion; import net.minecraft.advancements.critereon.*; import net.minecraft.core.HolderLookup; import net.minecraft.network.chat.Component; @@ -19,6 +18,8 @@ import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; import net.nuclearteam.createnuclear.CreateNuclear; +import net.minecraft.core.HolderLookup.Provider; + import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -28,18 +29,18 @@ @SuppressWarnings("unused") public class CreateNuclearAdvancement { - static final ResourceLocation BACKGROUND = CreateNuclear.asResource("textures/block/steel_block.png"); + static final ResourceLocation BACKGROUND = CreateNuclear.asResource("textures/gui/advancements/backgrounds/background_advancement.png"); static final String LANG = "advancement." + CreateNuclear.MOD_ID + "."; static final String SECRET_SUFFIX = "\n\u00A77(Hidden Advancement)"; - private final Advancement.Builder mcBuilder = Advancement.Builder.advancement(); - private SimpleCreateTrigger builtinTrigger; + private final Advancement.Builder builder = Advancement.Builder.advancement(); + private SimpleCreateNuclearTrigger builtinTrigger; private CreateNuclearAdvancement parent; - private final Builder createBuilder = new Builder(); + private final Builder createNuclearBuilder = new Builder(); AdvancementHolder datagenResult; - private final String id; + final String id; private String title; private String description; @@ -47,14 +48,14 @@ public class CreateNuclearAdvancement { public CreateNuclearAdvancement(String id, UnaryOperator b) { this.id = id; - b.apply(createBuilder); + b.apply(createNuclearBuilder); - if (!createBuilder.externalTrigger) { + if (!createNuclearBuilder.externalTrigger) { builtinTrigger = CNTriggers.addSimple(id + "_builtin"); - mcBuilder.addCriterion("0", builtinTrigger.createCriterion(builtinTrigger.instance())); + builder.addCriterion("0", builtinTrigger.createCriterion(builtinTrigger.instance())); } - if (createBuilder.type == CreateNuclearAdvancement.TaskType.SECRET) + if (createNuclearBuilder.type == TaskType.SECRET) description += SECRET_SUFFIX; CNAdvancement.ENTRIES.add(this); @@ -92,17 +93,22 @@ public void awardTo(Player player) { void save(Consumer t, HolderLookup.Provider registries) { if (parent != null) - mcBuilder.parent(parent.datagenResult); + builder.parent(parent.datagenResult); - if (createBuilder.func != null) - createBuilder.icon(createBuilder.func.apply(registries)); + if (createNuclearBuilder.func != null) + createNuclearBuilder.icon(createNuclearBuilder.func.apply(registries)); - mcBuilder.display(createBuilder.icon, Component.translatable(titleKey()), + builder.display( + createNuclearBuilder.icon, + Component.translatable(titleKey()), Component.translatable(descriptionKey()).withStyle(s -> s.withColor(0xDBA213)), - id.equals("root") ? BACKGROUND : null, createBuilder.type.advancementType, createBuilder.type.toast, - createBuilder.type.announce, createBuilder.type.hide); - - datagenResult = mcBuilder.save(t, CreateNuclear.asResource(id).toString()); + id.equals("root") ? BACKGROUND : null, + createNuclearBuilder.type.advancementType, + createNuclearBuilder.type.toast, + createNuclearBuilder.type.announce, + createNuclearBuilder.type.hide + ); + datagenResult = builder.save(t, CreateNuclear.asResource(id).toString()); } void provideLang(BiConsumer consumer) { @@ -125,8 +131,8 @@ enum TaskType { private final boolean announce; private final boolean hide; - TaskType(AdvancementType advancementType, boolean toast, boolean announce, boolean hide) { - this.advancementType = advancementType; + TaskType(AdvancementType frame, boolean toast, boolean announce, boolean hide) { + this.advancementType = frame; this.toast = toast; this.announce = announce; this.hide = hide; @@ -139,7 +145,7 @@ class Builder { private boolean externalTrigger; private int keyIndex; private ItemStack icon; - private Function func; + private Function func; Builder special(TaskType type) { this.type = type; @@ -164,7 +170,7 @@ Builder icon(ItemStack stack) { return this; } - Builder icon(Function func) { + Builder icon(Function func) { this.func = func; return this; } @@ -197,8 +203,7 @@ Builder whenItemCollected(ItemLike itemProvider) { } Builder whenItemCollected(TagKey tag) { - return externalTrigger(InventoryChangeTrigger.TriggerInstance - .hasItems(ItemPredicate.Builder.item().of(tag).build())); + return externalTrigger(InventoryChangeTrigger.TriggerInstance.hasItems(ItemPredicate.Builder.item().of(tag).build())); } Builder awardedForFree() { @@ -206,12 +211,11 @@ Builder awardedForFree() { } Builder externalTrigger(Criterion trigger) { - mcBuilder.addCriterion(String.valueOf(keyIndex), trigger); + builder.addCriterion(String.valueOf(keyIndex), trigger); externalTrigger = true; keyIndex++; return this; } } - -} +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CriterionTriggerBase.java b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CriterionTriggerBase.java new file mode 100644 index 0000000..6463366 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/CriterionTriggerBase.java @@ -0,0 +1,70 @@ +package net.nuclearteam.createnuclear.foundation.advancement; + +import com.google.common.collect.Maps; +import net.minecraft.advancements.CriterionTrigger; +import net.minecraft.advancements.critereon.SimpleCriterionTrigger; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.PlayerAdvancements; +import net.minecraft.server.level.ServerPlayer; +import net.nuclearteam.createnuclear.CreateNuclear; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.function.Supplier; + +public abstract class CriterionTriggerBase implements CriterionTrigger { + private final ResourceLocation id; + protected final Map>> listeners = Maps.newHashMap(); + + public CriterionTriggerBase(String id) { + this.id = CreateNuclear.asResource(id); + } + + @Override + public void addPlayerListener(PlayerAdvancements playerAdvancements, Listener listener) { + Set> playerListeners = this.listeners.computeIfAbsent(playerAdvancements, k -> new HashSet<>()); + + playerListeners.add(listener); + } + + @Override + public void removePlayerListener(PlayerAdvancements playerAdvancements, Listener listener) { + Set> playerListeners = this.listeners.get(playerAdvancements); + + if (playerListeners != null) { + playerListeners.remove(listener); + if (playerListeners.isEmpty()) { + this.listeners.remove(playerAdvancements); + } + } + } + + @Override + public void removePlayerListeners(PlayerAdvancements playerAdvancements) { + this.listeners.remove(playerAdvancements); + } + + public ResourceLocation getId() { + return id; + } + + protected void trigger(ServerPlayer player, @Nullable List> suppliers) { + PlayerAdvancements playerAdvancements = player.getAdvancements(); + Set> playerListeners = this.listeners.get(playerAdvancements); + if (playerListeners != null) { + List> list = new LinkedList<>(); + + for (Listener listener : playerListeners) { + if (listener.trigger().test(suppliers)) { + list.add(listener); + } + } + + list.forEach(listener -> listener.run(playerAdvancements)); + } + } + + public abstract static class Instance implements SimpleCriterionTrigger.SimpleInstance { + protected abstract boolean test(@Nullable List> suppliers); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/SimpleCreateNuclearTrigger.java b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/SimpleCreateNuclearTrigger.java new file mode 100644 index 0000000..106a550 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/advancement/SimpleCreateNuclearTrigger.java @@ -0,0 +1,60 @@ +package net.nuclearteam.createnuclear.foundation.advancement; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.advancements.Criterion; +import net.minecraft.advancements.critereon.ContextAwarePredicate; +import net.minecraft.advancements.critereon.EntityPredicate; +import net.minecraft.advancements.critereon.SimpleCriterionTrigger; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; + +public class SimpleCreateNuclearTrigger extends CriterionTriggerBase { + + public SimpleCreateNuclearTrigger(String id) { + super(id); + } + + public void trigger(ServerPlayer player) { + super.trigger(player, null); + } + + public SimpleCreateNuclearTrigger.Instance instance() { + return new SimpleCreateNuclearTrigger.Instance(); + } + + @Override + public Codec codec() { + return Instance.CODEC; + } + + public static class Instance extends CriterionTriggerBase.Instance { + private static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(Instance::player) + ).apply(instance, Instance::new)); + + private final Optional player; + + public Instance() { + player = Optional.empty(); + } + + public Instance(Optional player) { + this.player = player; + } + + @Override + protected boolean test(@Nullable List> suppliers) { + return true; + } + + @Override + public Optional player() { + return player; + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/block/EventTriggerBlock.java b/src/main/java/net/nuclearteam/createnuclear/foundation/block/EventTriggerBlock.java deleted file mode 100644 index c7829ae..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/block/EventTriggerBlock.java +++ /dev/null @@ -1,38 +0,0 @@ -package net.nuclearteam.createnuclear.foundation.block; - -import net.createmod.catnip.platform.CatnipServices; -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.ItemInteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.nuclearteam.createnuclear.CNPackets; -import net.nuclearteam.createnuclear.CreateNuclear; -import net.nuclearteam.createnuclear.content.multiblock.controller.EventTriggerPacket; - -import javax.annotation.ParametersAreNonnullByDefault; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class EventTriggerBlock extends Block { - public EventTriggerBlock(Properties properties) { - super(properties); - } - - @Override - public ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) { - if (!level.isClientSide) { - // Send a packet to all clients around this block within 16 blocks - EventTriggerPacket packet = new EventTriggerPacket(100); // display for 100 ticks - CreateNuclear.LOGGER.warn("hum EventTriggerBlock ? {}", packet); - CatnipServices.NETWORK.sendToClientsAround((ServerLevel) level, pos, 16, packet); - } - return ItemInteractionResult.SUCCESS; - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/block/MultiDirectionalReactorBlock.java b/src/main/java/net/nuclearteam/createnuclear/foundation/block/MultiDirectionalReactorBlock.java new file mode 100644 index 0000000..790087c --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/block/MultiDirectionalReactorBlock.java @@ -0,0 +1,29 @@ +package net.nuclearteam.createnuclear.foundation.block; + +import com.mojang.math.MethodsReturnNonnullByDefault; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.DirectionProperty; + +@MethodsReturnNonnullByDefault +@SuppressWarnings("deprecation") +public abstract class MultiDirectionalReactorBlock extends Block { + public static final DirectionProperty FACING = BlockStateProperties.FACING; + + public MultiDirectionalReactorBlock(Properties properties) { + super(properties); + } + + @Override + public BlockState rotate(BlockState state, Rotation rotation) { + return state.setValue(FACING, rotation.rotate(state.getValue(FACING))); + } + + @Override + public BlockState mirror(BlockState state, Mirror mirror) { + return state.rotate(mirror.getRotation(state.getValue(FACING))); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/damageTypes/CNDamageSources.java b/src/main/java/net/nuclearteam/createnuclear/foundation/damageTypes/CNDamageSources.java new file mode 100644 index 0000000..eb82700 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/damageTypes/CNDamageSources.java @@ -0,0 +1,37 @@ +package net.nuclearteam.createnuclear.foundation.damagesTypes; + +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageType; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.nuclearteam.createnuclear.CNDamageTypes; + +import javax.annotation.Nullable; + +public class CNDamageSources { + public static DamageSource radiation(Level level) { + return source(CNDamageTypes.RADIATION, level); + } + public static DamageSource fanRadiation(Level level) { + return source(CNDamageTypes.FAN_RADIATION, level); + } + + private static DamageSource source(ResourceKey key, LevelReader level) { + Registry registry = level.registryAccess().registryOrThrow(Registries.DAMAGE_TYPE); + return new DamageSource(registry.getHolderOrThrow(key)); + } + + private static DamageSource source(ResourceKey key, LevelReader level, @Nullable Entity entity) { + Registry registry = level.registryAccess().registryOrThrow(Registries.DAMAGE_TYPE); + return new DamageSource(registry.getHolderOrThrow(key), entity); + } + + private static DamageSource source(ResourceKey key, LevelReader level, @Nullable Entity causingEntity, @Nullable Entity directEntity) { + Registry registry = level.registryAccess().registryOrThrow(Registries.DAMAGE_TYPE); + return new DamageSource(registry.getHolderOrThrow(key), causingEntity, directEntity); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/CNBuilderTransformers.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/CNBuilderTransformers.java new file mode 100644 index 0000000..612154c --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/CNBuilderTransformers.java @@ -0,0 +1,97 @@ +package net.nuclearteam.createnuclear.foundation.data; + +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateItemModelProvider; +import com.tterrag.registrate.util.entry.ItemEntry; +import com.tterrag.registrate.util.nullness.NonNullBiConsumer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.Item; +import net.neoforged.neoforge.client.model.generators.ItemModelBuilder; +import net.neoforged.neoforge.common.DeferredSpawnEggItem; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.biome.BiomeIrradiationExtractorItem; + +import java.util.List; +import java.util.function.Supplier; + +public class CNBuilderTransformers { + + /** + * Generates the item model for a dyeable anti-radiation armor piece. + *

+ * The undyed ("default") piece uses a flat 2D icon ({@code item/generated} with the + * {@code item/armors/default_anti_radiation_} sprite) instead of the 3D Blockbench + * model, since the dropped/inventory 3D rendering was problematic. The worn armor on the + * body is unaffected (handled by {@code AntiRadiationArmorModel}). + *

+ * One model override per {@link DyeColor} is added, driven by the client-side + * {@code createnuclear:cloth_color} item property (see {@code CreateNuclearClient}). Each + * per-color child model still re-textures the 3D Blockbench geometry ({@code item//item}) + * with the matching {@code item/armors/_anti_radiation_suit} sheet. + *

+ * The texture keys differ per slot: the helmet geometry uses {@code layer0}/{@code particle}, + * the other pieces use {@code 14} — hence {@code textureKeys} is passed explicitly. + */ + public static NonNullBiConsumer, RegistrateItemModelProvider> coloredArmorModel(String slot, String... textureKeys) { + return (c, p) -> { + ResourceLocation baseParent = p.modLoc("item/" + c.getName() + "/item"); + ItemModelBuilder outer = p.generated(c, CreateNuclear.asResource("item/armors/default_anti_radiation_" + slot)); + // DyeColor.values() is ordered by id (0..15); overrides must be ascending by predicate + // value so vanilla override resolution selects the exact color (returns last match <= value).cloth + // The cloth_color property is clamped to [0,1] (see CreateNuclearClient), hence the + // (id+1)/16 normalization here must match the value returned there exactly. + for (DyeColor color : DyeColor.values()) { + String colorName = color.getSerializedName(); + ItemModelBuilder child = p.withExistingParent("item/colored/" + colorName + "_anti_radiation_" + slot, baseParent); + for (String key : textureKeys) { + child.texture(key, "models/armor/" + colorName + "_anti_radiation_suit"); + } + outer.override() + .predicate(CreateNuclear.asResource("cloth_color"), (color.getId() + 1) / 16f) + .model(child) + .end(); + } + }; + } + + /** + * Generates the per-tier model overrides for the biome restore cell, driven by the + * client-side {@code createnuclear:charge} item property (see {@code CreateNuclearClient}). + * Overrides must stay ascending by predicate value (vanilla resolves to the last match <= value), + * and the thresholds here must match the ratio returned by {@code biomeRestoreItemProperties}. + */ + public static NonNullBiConsumer, RegistrateItemModelProvider> biomeRestoreModel() { + return (c, p) -> { + ItemModelBuilder outer = p.generated(c, CreateNuclear.asResource("item/biome_irradiation_extractor/empty")); + + record Tier(String name, float threshold) {} + List tiers = List.of( + new Tier("quarter", 0.25f), + new Tier("half", 0.5f), + new Tier("three_quarters", 0.75f), + new Tier("full", 1.0f) + ); + + for (Tier tier : tiers) { + ItemModelBuilder child = p.withExistingParent("item/biome_irradiation_extractor/" + tier.name(), p.mcLoc("item/generated")) + .texture("layer0", CreateNuclear.asResource("item/biome_irradiation_extractor/" + tier.name())); + + outer.override() + .predicate(CreateNuclear.asResource(BiomeIrradiationExtractorItem.TAG), tier.threshold()) + .model(child) + .end(); + } + }; + } + + public static ItemEntry spawnEgg(String name, Supplier> entity, int backgroundColor, int highlightColor, String nameItems) { + return CreateNuclear.REGISTRATE + .item(name, p -> new DeferredSpawnEggItem(entity, backgroundColor, highlightColor, p)) + .lang(nameItems) + .model((c, p) -> p.withExistingParent(c.getName(), ResourceLocation.parse("item/template_spawn_egg"))) + .register(); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNCompactingRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNCompactingRecipeGen.java index 73f46b4..4216ea3 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNCompactingRecipeGen.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNCompactingRecipeGen.java @@ -4,9 +4,8 @@ import com.simibubi.create.api.data.recipe.CompactingRecipeGen; import net.minecraft.core.HolderLookup; import net.minecraft.data.PackOutput; -import net.nuclearteam.createnuclear.CNFluids; import net.nuclearteam.createnuclear.CNItems; -import net.nuclearteam.createnuclear.CNTags; +import net.nuclearteam.createnuclear.CNTags.CNFluidTags; import net.nuclearteam.createnuclear.CreateNuclear; import java.util.concurrent.CompletableFuture; @@ -14,9 +13,14 @@ public class CNCompactingRecipeGen extends CompactingRecipeGen { GeneratedRecipe YELLOWCAKE = create(CreateNuclear.asResource("uranium_fluid_to_yellowcake"), b -> b - .require(CNFluids.URANIUM.get(), 100) + .require(CNFluidTags.URANIUM.tag, 100) .output(CNItems.YELLOWCAKE, 1) - ); + ), + THORIUM = create(CreateNuclear.asResource("thorium_fluid_to_thorium_ingot"), b -> b + .require(CNFluidTags.THORIUM.tag, 200) + .output(CNItems.THORIUM_INGOT, 1) + ) + ; public CNCompactingRecipeGen(PackOutput output, CompletableFuture registries) { diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNCrushingRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNCrushingRecipeGen.java index 994a431..98f27b9 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNCrushingRecipeGen.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNCrushingRecipeGen.java @@ -2,16 +2,22 @@ import com.simibubi.create.AllItems; import com.simibubi.create.api.data.recipe.CrushingRecipeGen; +import com.simibubi.create.content.decoration.palettes.AllPaletteStoneTypes; +import com.simibubi.create.content.kinetics.crusher.CrushingRecipe; +import com.simibubi.create.content.processing.recipe.StandardProcessingRecipe; import net.minecraft.core.HolderLookup; import net.minecraft.data.PackOutput; import net.minecraft.tags.ItemTags; import net.minecraft.world.item.Items; +import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Blocks; import net.nuclearteam.createnuclear.CNBlocks; import net.nuclearteam.createnuclear.CNItems; import net.nuclearteam.createnuclear.CreateNuclear; import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; public class CNCrushingRecipeGen extends CrushingRecipeGen { @@ -38,6 +44,18 @@ public class CNCrushingRecipeGen extends CrushingRecipeGen { .output(1, CNItems.URANIUM_POWDER,81) ), + RAW_THORIUM_BLOCK = create(() -> CNBlocks.RAW_THORIUM_BLOCK, b -> b + .duration(250) + .output(1, CNItems.THORIUM_DUST, 9) + .output(0.5f, CNItems.THORIUM_DUST, 72) + ), + + RAW_THORIUM_ITEM = create(() -> CNItems.RAW_THORIUM, b -> b + .duration(125) + .output(1, CNItems.THORIUM_DUST, 1) + .output(0.5f, CNItems.THORIUM_DUST, 8) + ), + RAW_ZINC = create(() -> AllItems.RAW_ZINC, b -> b.duration(250) .output(1, AllItems.CRUSHED_ZINC, 1) .output(.75f, AllItems.EXP_NUGGET, 1) @@ -49,6 +67,13 @@ public class CNCrushingRecipeGen extends CrushingRecipeGen { .output(1, AllItems.CRUSHED_COPPER, 1) .output(.75f, AllItems.EXP_NUGGET, 1) .output(.15f, CNItems.LEAD_NUGGET,1) + ), + + NITRATE = create("nitrate", b -> b + .require(AllPaletteStoneTypes.LIMESTONE.materialTag) + .duration(250) + .output(.6f, CNItems.NITRATE, 1) + .output(.4f, CNItems.LEAD_NUGGET, 1) ) ; @@ -56,7 +81,9 @@ public CNCrushingRecipeGen(PackOutput output, CompletableFuture singleIngredient, + UnaryOperator> transform) { + return create(CreateNuclear.MOD_ID, singleIngredient, transform); + } } diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNDeployingRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNDeployingRecipeGen.java new file mode 100644 index 0000000..83227ef --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNDeployingRecipeGen.java @@ -0,0 +1,55 @@ +package net.nuclearteam.createnuclear.foundation.data.recipe; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.api.data.recipe.DeployingRecipeGen; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.ItemLike; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.CreateNuclear; + +import java.util.concurrent.CompletableFuture; + +public class CNDeployingRecipeGen extends DeployingRecipeGen { + + GeneratedRecipe REACTOR_ROD_INPUT = deploying("reactor_rod_input_from_hopper_and_reactor_casing", + Items.HOPPER, + CNBlocks.REACTOR_CASING.get(), + CNBlocks.REACTOR_ROD_INPUT.get() + ); + + GeneratedRecipe REACTOR_FLUID_INPUT = deploying("reactor_fluid_input_from_fluid_pipe_and_reactor_casing", + AllBlocks.FLUID_PIPE.asItem(), + CNBlocks.REACTOR_CASING.get(), + CNBlocks.REACTOR_FLUID_INPUT.get() + ); + + GeneratedRecipe REACTOR_OUTPUT = deploying("reactor_output_from_shaft_and_reactor_casing", + AllBlocks.SHAFT.asItem(), + CNBlocks.REACTOR_CASING.get(), + CNBlocks.REACTOR_OUTPUT.get() + ); + + protected GeneratedRecipe deploying(String name, Ingredient ingredient, ItemLike input, ItemLike output) { + return create(CreateNuclear.asResource(name), b -> + b.require(input) + .require(ingredient) + .output(output) + ); + } + + protected GeneratedRecipe deploying(String name, Item ingredient, ItemLike input, ItemLike output) { + return create(CreateNuclear.asResource(name), b -> + b.require(input) + .require(ingredient) + .output(output) + ); + } + + public CNDeployingRecipeGen(PackOutput output, CompletableFuture registries) { + super(output, registries, CreateNuclear.MOD_ID); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNEnrichedRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNEnrichedRecipeGen.java index cfa8df7..b271401 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNEnrichedRecipeGen.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNEnrichedRecipeGen.java @@ -7,6 +7,7 @@ import net.nuclearteam.createnuclear.CNBlocks; import net.nuclearteam.createnuclear.CNItems; import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.data.recipe.EnrichedRecipeGen; import java.util.concurrent.CompletableFuture; diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNItemApplicationRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNItemApplicationRecipeGen.java index 18589b3..99a1c33 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNItemApplicationRecipeGen.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNItemApplicationRecipeGen.java @@ -22,31 +22,19 @@ public class CNItemApplicationRecipeGen extends ItemApplicationRecipeGen { CNBlocks.REACTOR_CASING.get() ); - GeneratedRecipe REACTOR_OUTPUT = itemApplication("reactor_output_from_shaft_and_reactor_casing", - AllBlocks.SHAFT.asItem(), - CNBlocks.REACTOR_CASING.get(), - CNBlocks.REACTOR_OUTPUT.get() - ); - - GeneratedRecipe REACTOR_INPUT = itemApplication("reactor_input_from_hopper_and_reactor_casing", - Items.HOPPER, - CNBlocks.REACTOR_CASING.get(), - CNBlocks.REACTOR_INPUT.get() - ); - protected GeneratedRecipe itemApplication(String name, Ingredient ingredient, ItemLike input, ItemLike output) { return create(CreateNuclear.asResource(name), b -> - b.require(input) - .require(ingredient) - .output(output) + b.require(input) + .require(ingredient) + .output(output) ); } protected GeneratedRecipe itemApplication(String name, Item ingredient, ItemLike input, ItemLike output) { return create(CreateNuclear.asResource(name), b -> - b.require(input) - .require(ingredient) - .output(output) + b.require(input) + .require(ingredient) + .output(output) ); } diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNMechanicalCraftingRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNMechanicalCraftingRecipeGen.java index ada2a3f..6da9234 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNMechanicalCraftingRecipeGen.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNMechanicalCraftingRecipeGen.java @@ -44,11 +44,21 @@ public class CNMechanicalCraftingRecipeGen extends MechanicalCraftingRecipeGen { .patternLine("U ") ), + THORIUM_ROD = create(CNItems.THORIUM_ROD::get) + .recipe(b -> b + .key('U', Ingredient.of(CNItems.THORIUM_INGOT)) + .patternLine("U ") + .patternLine(" U ") + .patternLine(" U ") + .patternLine(" U ") + .patternLine(" U") + ), + REACTOR_MAIN_FRAME = create(CNBlocks.REACTOR_FRAME::get) .recipe(b -> b .key('C', Ingredient.of(CNBlocks.REACTOR_CASING)) .key('G', Ingredient.of(CNBlocks.REINFORCED_GLASS)) - .key('B', Ingredient.of(CNFluids.URANIUM.get().getBucket())) + .key('B', Ingredient.of(Items.BUCKET)) .key('S', Ingredient.of(CNTags.forgeItemTag("ingots/steel"))) .patternLine("CCCCC") .patternLine("CSGSC") @@ -96,7 +106,20 @@ public class CNMechanicalCraftingRecipeGen extends MechanicalCraftingRecipeGen { .patternLine("CSBSC") .patternLine("CPSPC") .patternLine("CCCCC") - ); + ), + + REACTOR_ALARM = create(CNBlocks.REACTOR_ALARM::get) + .recipe(b -> b + .key('C', Ingredient.of(CNBlocks.REACTOR_CASING)) + .key('N', Ingredient.of(Blocks.NOTE_BLOCK)) + .key('R', Ingredient.of(Blocks.REPEATER)) + .key('L', Ingredient.of(Items.CLOCK)) + .patternLine("CCCCC") + .patternLine("CNRNC") + .patternLine("CRLRC") + .patternLine("CNRNC") + .patternLine("CCCCC") + ); public CNMechanicalCraftingRecipeGen(PackOutput output, CompletableFuture registries) { diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNMixingRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNMixingRecipeGen.java index a95cba5..c1c7e0d 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNMixingRecipeGen.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNMixingRecipeGen.java @@ -1,8 +1,10 @@ package net.nuclearteam.createnuclear.foundation.data.recipe; import com.simibubi.create.api.data.recipe.MixingRecipeGen; +import com.simibubi.create.content.processing.recipe.HeatCondition; import net.minecraft.core.HolderLookup; import net.minecraft.data.PackOutput; +import net.minecraft.world.item.Items; import net.neoforged.neoforge.common.Tags; import net.nuclearteam.createnuclear.CNFluids; import net.nuclearteam.createnuclear.CNItems; @@ -23,6 +25,19 @@ public class CNMixingRecipeGen extends MixingRecipeGen { URANIUM_FLUID = create("uranium_fluid", b -> b .require(CNTags.forgeItemTag("dusts/uranium")) .output(CNFluids.URANIUM.get(), 25) + ), + + THORIUM_FLUID = create("thorium_fluid", b -> b + .require(CNTags.forgeItemTag("dusts/thorium")) + .output(CNFluids.THORIUM.get(), 25) + .requiresHeat(HeatCondition.HEATED) + ), + + NITROGEN = create("liquid_nitrogen", b -> b + .require(CNItems.COOLED_NITROGEN_CONCENTRATE) + .duration(20) + .require(Items.ICE) + .output(CNFluids.LIQUID_NITROGEN.get(), 100) ) ; diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNRecipeProvider.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNRecipeProvider.java index efabd09..81369bd 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNRecipeProvider.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNRecipeProvider.java @@ -1,12 +1,6 @@ package net.nuclearteam.createnuclear.foundation.data.recipe; -import com.simibubi.create.Create; import com.simibubi.create.api.data.recipe.ProcessingRecipeGen; -import com.simibubi.create.content.processing.recipe.ProcessingRecipe; -import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; -import com.simibubi.create.foundation.data.recipe.CreateRecipeProvider; -import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; -import net.createmod.catnip.platform.CatnipServices; import net.minecraft.core.HolderLookup; import net.minecraft.data.CachedOutput; import net.minecraft.data.DataGenerator; @@ -14,16 +8,10 @@ import net.minecraft.data.PackOutput; import net.minecraft.data.recipes.RecipeOutput; import net.minecraft.data.recipes.RecipeProvider; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.level.ItemLike; -import net.nuclearteam.createnuclear.CreateNuclear; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.function.Supplier; -import java.util.function.UnaryOperator; public abstract class CNRecipeProvider extends RecipeProvider { @@ -44,21 +32,22 @@ public static void registerAllProcessing(DataGenerator gen, PackOutput output, C GENERATORS.add(new CNMixingRecipeGen(output, registries)); GENERATORS.add(new CNPressingRecipeGen(output, registries)); GENERATORS.add(new CNEnrichedRecipeGen(output, registries)); + GENERATORS.add(new CNSnowPowderRecipeGen(output, registries)); GENERATORS.add(new CNWashingRecipeGen(output, registries)); - + GENERATORS.add(new CNDeployingRecipeGen(output, registries)); gen.addProvider(true, new DataProvider() { @Override public String getName() { - return "Create's Processing Recipes"; + return "CreateNuclear's Processing Recipes"; } @Override public CompletableFuture run(CachedOutput dc) { return CompletableFuture.allOf(GENERATORS.stream() - .map(gen -> gen.run(dc)) - .toArray(CompletableFuture[]::new)); + .map(gen -> gen.run(dc)) + .toArray(CompletableFuture[]::new)); } }); } diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNShapelessRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNShapelessRecipeGen.java deleted file mode 100644 index d75ffd4..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNShapelessRecipeGen.java +++ /dev/null @@ -1,504 +0,0 @@ -package net.nuclearteam.createnuclear.foundation.data.recipe; - -import com.google.common.base.Supplier; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import com.simibubi.create.Create; -import com.simibubi.create.api.data.recipe.BaseRecipeProvider; -import com.simibubi.create.foundation.mixin.accessor.MappedRegistryAccessor; -import com.tterrag.registrate.util.entry.BlockEntry; -import com.tterrag.registrate.util.entry.ItemProviderEntry; -import net.createmod.catnip.registry.RegisteredObjectsHelper; -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.advancements.Advancement; -import net.minecraft.advancements.AdvancementHolder; -import net.minecraft.advancements.critereon.ItemPredicate; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderLookup; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.data.PackOutput; -import net.minecraft.data.recipes.*; -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.*; -import net.minecraft.world.level.ItemLike; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.neoforged.neoforge.common.conditions.ICondition; -import net.neoforged.neoforge.common.conditions.ModLoadedCondition; -import net.neoforged.neoforge.common.conditions.NotCondition; -import net.nuclearteam.createnuclear.CNItems; -import net.nuclearteam.createnuclear.CNTags; -import net.nuclearteam.createnuclear.CreateNuclear; -import net.nuclearteam.createnuclear.content.equipment.cloth.ClothItem; -import org.jetbrains.annotations.Nullable; - -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; -import java.util.function.UnaryOperator; - -@SuppressWarnings("unused") -public class CNShapelessRecipeGen extends BaseRecipeProvider { - - private final Marker SHAPELESS = enterFolder("shapeless"); - - private final Marker SHAPELESS_CLOTH = enterFolder("shapeless/cloth"); - - - static class Marker { - } - - String currentFolder = ""; - - Marker enterFolder(String folder) { - currentFolder = folder; - return new Marker(); - } - - GeneratedRecipeBuilder create(com.google.common.base.Supplier result) { - return new GeneratedRecipeBuilder(currentFolder, result); - } - - GeneratedRecipeBuilder create(ResourceLocation result) { - return new GeneratedRecipeBuilder(currentFolder, result); - } - - GeneratedRecipeBuilder create(ItemProviderEntry result) { - return create(result::get); - } - - GeneratedRecipe createSpecial(Function> builder, String recipeType, - String path) { - ResourceLocation location = Create.asResource(recipeType + "/" + currentFolder + "/" + path); - return register(consumer -> { - SpecialRecipeBuilder b = SpecialRecipeBuilder.special(builder); - b.save(consumer, location.toString()); - }); - } - - GeneratedRecipe blastCrushedMetal(com.google.common.base.Supplier result, com.google.common.base.Supplier ingredient) { - return create(result::get).withSuffix("_from_crushed") - .viaCooking(ingredient) - .rewardXP(.1f) - .inBlastFurnace(); - } - - GeneratedRecipe recycleGlass(BlockEntry ingredient) { - return create(() -> Blocks.GLASS).withSuffix("_from_" + ingredient.getId() - .getPath()) - .viaCooking(ingredient::get) - .forDuration(50) - .inFurnace(); - } - - GeneratedRecipe recycleGlassPane(BlockEntry ingredient) { - return create(() -> Blocks.GLASS_PANE).withSuffix("_from_" + ingredient.getId() - .getPath()) - .viaCooking(ingredient::get) - .forDuration(50) - .inFurnace(); - } - - GeneratedRecipe blastFurnaceRecipe(com.google.common.base.Supplier result, com.google.common.base.Supplier ingredient, String suffix, int count) { - return create(result::get).withSuffix(suffix) - .returns(count) - .viaCooking(ingredient) - .rewardXP(.1f) - .inBlastFurnace(); - } - - GeneratedRecipe blastFurnaceRecipeTags(com.google.common.base.Supplier result, com.google.common.base.Supplier> ingredient, String suffix, int count) { - return create(result::get).withSuffix(suffix) - .returns(count) - .viaCookingTag(ingredient) - .rewardXP(.1f) - .inBlastFurnace(); - } - - GeneratedRecipe metalCompacting(List> variants, - List>> ingredients) { - GeneratedRecipe result = null; - for (int i = 0; i + 1 < variants.size(); i++) { - ItemProviderEntry currentEntry = variants.get(i); - ItemProviderEntry nextEntry = variants.get(i + 1); - com.google.common.base.Supplier> currentIngredient = ingredients.get(i); - com.google.common.base.Supplier> nextIngredient = ingredients.get(i + 1); - - result = create(nextEntry).withSuffix("_from_compacting") - .unlockedBy(currentEntry::get) - .viaShaped(b -> b.pattern("###") - .pattern("###") - .pattern("###") - .define('#', currentIngredient.get())); - - result = create(currentEntry).returns(9) - .withSuffix("_from_decompacting") - .unlockedBy(nextEntry::get) - .viaShapeless(b -> b.requires(nextIngredient.get())); - } - return result; - } - - GeneratedRecipe conversionCycle(List> cycle) { - GeneratedRecipe result = null; - for (int i = 0; i < cycle.size(); i++) { - ItemProviderEntry currentEntry = cycle.get(i); - ItemProviderEntry nextEntry = cycle.get((i + 1) % cycle.size()); - result = create(nextEntry).withSuffix("_from_conversion") - .unlockedBy(currentEntry::get) - .viaShapeless(b -> b.requires(currentEntry.get())); - } - return result; - } - - GeneratedRecipe clearData(ItemProviderEntry item) { - return create(item).withSuffix("_clear") - .unlockedBy(item::get) - .viaShapeless(b -> b.requires(item.get())); - } - - @Override - protected void buildRecipes(RecipeOutput output, HolderLookup.Provider holderLookup) { - all.forEach(c -> c.register(output)); - CreateNuclear.LOGGER.info("{} registered {} recipe{}", getName(), all.size(), all.size() == 1 ? "" : "s"); - } - -// protected GeneratedRecipe register(GeneratedRecipe recipe) { -// all.add(recipe); -// return recipe; -// } - - class GeneratedRecipeBuilder { - - private final String path; - private String suffix; - private com.google.common.base.Supplier result; - private ResourceLocation compatDatagenOutput; - List recipeConditions; - - private com.google.common.base.Supplier unlockedBy; - private int amount; - - private GeneratedRecipeBuilder(String path) { - this.path = path; - this.recipeConditions = new ArrayList<>(); - this.suffix = ""; - this.amount = 1; - } - - public GeneratedRecipeBuilder(String path, com.google.common.base.Supplier result) { - this(path); - this.result = result; - } - - public GeneratedRecipeBuilder(String path, ResourceLocation result) { - this(path); - this.compatDatagenOutput = result; - } - - GeneratedRecipeBuilder returns(int amount) { - this.amount = amount; - return this; - } - - GeneratedRecipeBuilder unlockedBy(com.google.common.base.Supplier item) { - this.unlockedBy = () -> ItemPredicate.Builder.item() - .of(item.get()) - .build(); - return this; - } - - GeneratedRecipeBuilder unlockedByTag(com.google.common.base.Supplier> tag) { - this.unlockedBy = () -> ItemPredicate.Builder.item() - .of(tag.get()) - .build(); - return this; - } - - GeneratedRecipeBuilder whenModLoaded(String mod) { - return withCondition(new ModLoadedCondition(mod)); - } - - GeneratedRecipeBuilder whenModMissing(String mod) { - return withCondition(new NotCondition(new ModLoadedCondition(mod))); - } - - GeneratedRecipeBuilder withCondition(ICondition condition) { - recipeConditions.add(condition); - return this; - } - - GeneratedRecipeBuilder withSuffix(String suffix) { - this.suffix = suffix; - return this; - } - - // FIXME 5.1 refactor - recipe categories as markers instead of sections? - GeneratedRecipe viaShaped(UnaryOperator builder) { - return register(consumer -> { - ShapedRecipeBuilder b = - builder.apply(ShapedRecipeBuilder.shaped(RecipeCategory.MISC, result.get(), amount)); - if (unlockedBy != null) - b.unlockedBy("has_item", inventoryTrigger(unlockedBy.get())); - b.save(consumer, createLocation("crafting")); - }); - } - - GeneratedRecipe viaShapeless(UnaryOperator builder) { - return register(recipeOutput -> { - ShapelessRecipeBuilder b = - builder.apply(ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, result.get(), amount)); - if (unlockedBy != null) - b.unlockedBy("has_item", inventoryTrigger(unlockedBy.get())); - - RecipeOutput conditionalOutput = recipeOutput.withConditions(recipeConditions.toArray(new ICondition[0])); - - b.save(recipeOutput, createLocation("crafting")); - }); - } - - GeneratedRecipe viaNetheriteSmithing(com.google.common.base.Supplier base, com.google.common.base.Supplier upgradeMaterial) { - return register(consumer -> { - SmithingTransformRecipeBuilder b = - SmithingTransformRecipeBuilder.smithing(Ingredient.of(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE), - Ingredient.of(base.get()), upgradeMaterial.get(), RecipeCategory.COMBAT, result.get() - .asItem()); - b.unlocks("has_item", inventoryTrigger(ItemPredicate.Builder.item() - .of(base.get()) - .build())); - b.save(consumer, createLocation("crafting")); - }); - } - - private ResourceLocation createSimpleLocation(String recipeType) { - return Create.asResource(recipeType + "/" + getRegistryName().getPath() + suffix); - } - - private ResourceLocation createLocation(String recipeType) { - return Create.asResource(recipeType + "/" + path + "/" + getRegistryName().getPath() + suffix); - } - - private ResourceLocation getRegistryName() { - return compatDatagenOutput == null ? RegisteredObjectsHelper.getKeyOrThrow(result.get() - .asItem()) : compatDatagenOutput; - } - - GeneratedCookingRecipeBuilder viaCooking(com.google.common.base.Supplier item) { - return unlockedBy(item).viaCookingIngredient(() -> Ingredient.of(item.get())); - } - - GeneratedCookingRecipeBuilder viaCookingTag(com.google.common.base.Supplier> tag) { - return unlockedByTag(tag).viaCookingIngredient(() -> Ingredient.of(tag.get())); - } - - GeneratedCookingRecipeBuilder viaCookingIngredient(Supplier ingredient) { - return new GeneratedCookingRecipeBuilder(ingredient); - } - - class GeneratedCookingRecipeBuilder { - - private final Supplier ingredient; - private float exp; - private int cookingTime; - - GeneratedCookingRecipeBuilder(Supplier ingredient) { - this.ingredient = ingredient; - cookingTime = 200; - exp = 0; - } - - GeneratedCookingRecipeBuilder forDuration(int duration) { - cookingTime = duration; - return this; - } - - GeneratedCookingRecipeBuilder rewardXP(float xp) { - exp = xp; - return this; - } - - GeneratedRecipe inFurnace() { - return inFurnace(b -> b); - } - - GeneratedRecipe inFurnace(UnaryOperator builder) { - return create(RecipeSerializer.SMELTING_RECIPE, builder, SmeltingRecipe::new, 1); - } - - GeneratedRecipe inSmoker() { - return inSmoker(b -> b); - } - - GeneratedRecipe inSmoker(UnaryOperator builder) { - create(RecipeSerializer.SMELTING_RECIPE, builder, SmeltingRecipe::new, 1); - create(RecipeSerializer.CAMPFIRE_COOKING_RECIPE, builder, CampfireCookingRecipe::new, 3); - return create(RecipeSerializer.SMOKING_RECIPE, builder, SmokingRecipe::new, .5f); - } - - GeneratedRecipe inBlastFurnace() { - return inBlastFurnace(b -> b); - } - - GeneratedRecipe inBlastFurnace(UnaryOperator builder) { - create(RecipeSerializer.SMELTING_RECIPE, builder, SmeltingRecipe::new, 1); - return create(RecipeSerializer.BLASTING_RECIPE, builder, BlastingRecipe::new, .5f); - } - - private GeneratedRecipe create(RecipeSerializer serializer, - UnaryOperator builder, AbstractCookingRecipe.Factory factory, float cookingTimeModifier) { - return register(recipeOutput -> { - boolean isOtherMod = compatDatagenOutput != null; - - SimpleCookingRecipeBuilder b = builder.apply(SimpleCookingRecipeBuilder.generic(ingredient.get(), - RecipeCategory.MISC, isOtherMod ? Items.DIRT : result.get(), exp, - (int) (cookingTime * cookingTimeModifier), serializer, factory)); - if (unlockedBy != null) - b.unlockedBy("has_item", inventoryTrigger(unlockedBy.get())); - - RecipeOutput conditionalOutput = recipeOutput.withConditions(recipeConditions.toArray(new ICondition[0])); - - b.save( - isOtherMod ? new ModdedCookingRecipeOutput(conditionalOutput, compatDatagenOutput) : conditionalOutput, - createSimpleLocation(RegisteredObjectsHelper.getKeyOrThrow(serializer).getPath()) - ); - }); - } - } - } - - - - public CNShapelessRecipeGen(PackOutput output, CompletableFuture registries) { - super(output, registries, CreateNuclear.MOD_ID); - } - - @ParametersAreNonnullByDefault - @MethodsReturnNonnullByDefault - private static class ModdedCookingRecipeOutputShim implements Recipe { - - private static final Map, ModdedCookingRecipeOutputShim.Serializer> serializers = new ConcurrentHashMap<>(); - - private final Recipe wrapped; - private final ResourceLocation overrideID; - - private ModdedCookingRecipeOutputShim(Recipe wrapped, ResourceLocation overrideID) { - this.wrapped = wrapped; - this.overrideID = overrideID; - } - - @Override - public boolean matches(RecipeInput recipeInput, Level level) { - throw new AssertionError("Only for datagen output"); - } - - @Override - public ItemStack assemble(RecipeInput input, HolderLookup.Provider registries) { - throw new AssertionError("Only for datagen output"); - } - - @Override - public boolean canCraftInDimensions(int pWidth, int pHeight) { - throw new AssertionError("Only for datagen output"); - } - - @Override - public ItemStack getResultItem(HolderLookup.Provider registries) { - throw new AssertionError("Only for datagen output"); - } - - @Override - public RecipeSerializer getSerializer() { - return serializers.computeIfAbsent( - getType(), - t -> ModdedCookingRecipeOutputShim.Serializer.create(wrapped) - ); - } - - @Override - public RecipeType getType() { - return wrapped.getType(); - } - - private record Serializer( - MapCodec> wrappedCodec) implements RecipeSerializer { - private static ModdedCookingRecipeOutputShim.Serializer create(Recipe wrapped) { - RecipeSerializer wrappedSerializer = wrapped.getSerializer(); - @SuppressWarnings("unchecked") - ModdedCookingRecipeOutputShim.Serializer serializer = new ModdedCookingRecipeOutputShim.Serializer((MapCodec>) wrappedSerializer.codec()); - - // Need to do some registry injection to get the Recipe/Registry#byNameCodec to encode the right type for this - // getResourceKey and getId - // byValue and toId - // Holder.Reference: key - if (BuiltInRegistries.RECIPE_SERIALIZER instanceof com.simibubi.create.foundation.mixin.accessor.MappedRegistryAccessor mra) { - @SuppressWarnings("unchecked") - com.simibubi.create.foundation.mixin.accessor.MappedRegistryAccessor> mra$ = (MappedRegistryAccessor>) mra; - - int wrappedId = mra$.getToId().getOrDefault(wrappedSerializer, -1); - ResourceKey> wrappedKey = mra$.getByValue().get(wrappedSerializer).key(); - - mra$.getToId().put(serializer, wrappedId); - //noinspection DataFlowIssue - it is ok to pass null as the owner, because this is only being used for serialization - mra$.getByValue().put(serializer, Holder.Reference.createStandAlone(null, wrappedKey)); - } else { - throw new AssertionError("ModdedCookingRecipeOutputShim will not be able to" + - " serialize without injecting into a registry. Expected" + - " BuiltInRegistries.RECIPE_SERIALIZER to be of class MappedRegistry, is of class " + - BuiltInRegistries.RECIPE_SERIALIZER.getClass() - ); - } - return serializer; - } - - @Override - public MapCodec codec() { - return RecordCodecBuilder.mapCodec(instance -> instance.group( - wrappedCodec.forGetter(i -> i.wrapped), - ModdedCookingRecipeOutputShim.FakeItemStack.CODEC.fieldOf("result").forGetter(i -> new ModdedCookingRecipeOutputShim.FakeItemStack(i.overrideID)) - ).apply(instance, (wrappedRecipe, fakeItemStack) -> { - throw new AssertionError("Only for datagen output"); - })); - } - - @Override - public StreamCodec streamCodec() { - throw new AssertionError("Only for datagen output"); - } - } - - private record FakeItemStack(ResourceLocation id) { - public static Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - ResourceLocation.CODEC.fieldOf("id").forGetter(ModdedCookingRecipeOutputShim.FakeItemStack::id) - ).apply(instance, ModdedCookingRecipeOutputShim.FakeItemStack::new)); - } - } - - @ParametersAreNonnullByDefault - @MethodsReturnNonnullByDefault - private record ModdedCookingRecipeOutput(RecipeOutput wrapped, ResourceLocation outputOverride) implements RecipeOutput { - - @Override - public Advancement.Builder advancement() { - return wrapped.advancement(); - } - - @Override - public void accept(ResourceLocation id, Recipe recipe, @Nullable AdvancementHolder advancement, ICondition... conditions) { - wrapped.accept(id, new ModdedCookingRecipeOutputShim(recipe, outputOverride), advancement, conditions); - } - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNSnowPowderRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNSnowPowderRecipeGen.java new file mode 100644 index 0000000..627600d --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNSnowPowderRecipeGen.java @@ -0,0 +1,21 @@ +package net.nuclearteam.createnuclear.foundation.data.recipe; + +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.nuclearteam.createnuclear.CNItems; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.data.recipe.SnowPowderRecipeGen; + +import java.util.concurrent.CompletableFuture; + +public class CNSnowPowderRecipeGen extends SnowPowderRecipeGen { + + GeneratedRecipe + COOLED_NITROGEN_CONCENTRATE = convert(CNItems.NITROGEN_CONCENTRATE, CNItems.COOLED_NITROGEN_CONCENTRATE) + ; + + public CNSnowPowderRecipeGen(PackOutput output, CompletableFuture registries) { + super(output, registries, CreateNuclear.MOD_ID); + } + +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNStandardRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNStandardRecipeGen.java index e575c40..0680170 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNStandardRecipeGen.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNStandardRecipeGen.java @@ -89,14 +89,19 @@ public class CNStandardRecipeGen extends BaseRecipeProvider { ImmutableList.of(() -> CNTags.forgeItemTag("nuggets/lead"), () -> CNTags.forgeItemTag("ingots/lead"), () -> CNTags.forgeItemTag("storage_blocks/lead"))), STEEL_COMPACTING = metalCompacting(ImmutableList.of(CNItems.STEEL_NUGGET, CNItems.STEEL_INGOT, CNBlocks.STEEL_BLOCK), - ImmutableList.of(() -> CNTags.forgeItemTag("nuggets/steel"), () -> CNTags.forgeItemTag("ingots/steel"), () -> CNTags.forgeItemTag("storage_blocks/steel"))); + ImmutableList.of(() -> CNTags.forgeItemTag("nuggets/steel"), () -> CNTags.forgeItemTag("ingots/steel"), () -> CNTags.forgeItemTag("storage_blocks/steel"))), + + THORIUM_COMPACTING = metalCompacting(ImmutableList.of(CNItems.THORIUM_NUGGET, CNItems.THORIUM_INGOT, CNBlocks.THORIUM_BLOCK), + ImmutableList.of(() -> CNTags.forgeItemTag("nuggets/thorium"), () -> CNTags.forgeItemTag("ingots/thorium"), () -> CNTags.forgeItemTag("storage_blocks/thorium"))) + ; private final Marker BLAST_FURNACE = enterFolder("blast_furnace"); GeneratedRecipe - URANIUM_ORE_TO_URANIUM_POWDER = blastFurnaceRecipeTags(() -> CNItems.RAW_URANIUM::get, () -> CNItemTags.URANIUM_ORES.tag, "_for_uranium_ore", 4), - RAW_LEAD_ORES = blastFurnaceRecipeTags(() -> CNItems.LEAD_INGOT::get, () -> CNItemTags.LEAD_ORES.tag, "_for_lead_ore", 1), + URANIUM_ORE_TO_URANIUM_POWDER = blastFurnaceRecipeTags(() -> CNItems.RAW_URANIUM::get, () -> CNTags.forgeItemTag("ores/uranium"), "_for_uranium_ore", 4), + RAW_LEAD_ORES = blastFurnaceRecipeTags(() -> CNItems.LEAD_INGOT::get, () -> CNTags.forgeItemTag("ores/lead"), "_for_lead_ore", 1), RAW_LEAD = blastFurnaceRecipeTags(CNItems.LEAD_INGOT::get, () -> CNTags.forgeItemTag("raw_materials/lead"), "_for_raw_lead", 1), - CRUSHED_RAW_LEAD_TO_LEAD_BLAST_FURNACE = blastFurnaceRecipe(CNItems.LEAD_INGOT::get, AllItems.CRUSHED_LEAD::get, "_for_lead", 1) + CRUSHED_RAW_LEAD_TO_LEAD_BLAST_FURNACE = blastFurnaceRecipe(CNItems.LEAD_INGOT::get, AllItems.CRUSHED_LEAD::get, "_for_lead", 1), + NITROGEN_CONCENTRATE = blastFurnaceRecipe(CNItems.NITROGEN_CONCENTRATE::get, CNItems.NITRATE::get, "_for_nitrogen_concentrate", 1) ; static class Marker { @@ -483,9 +488,9 @@ private static ModdedCookingRecipeOutputShim.Serializer create(Recipe wrapped // getResourceKey and getId // byValue and toId // Holder.Reference: key - if (BuiltInRegistries.RECIPE_SERIALIZER instanceof com.simibubi.create.foundation.mixin.accessor.MappedRegistryAccessor mra) { + if (BuiltInRegistries.RECIPE_SERIALIZER instanceof MappedRegistryAccessor mra) { @SuppressWarnings("unchecked") - com.simibubi.create.foundation.mixin.accessor.MappedRegistryAccessor> mra$ = (MappedRegistryAccessor>) mra; + MappedRegistryAccessor> mra$ = (MappedRegistryAccessor>) mra; int wrappedId = mra$.getToId().getOrDefault(wrappedSerializer, -1); ResourceKey> wrappedKey = mra$.getByValue().get(wrappedSerializer).key(); @@ -540,4 +545,4 @@ public void accept(ResourceLocation id, Recipe recipe, @Nullable AdvancementH wrapped.accept(id, new ModdedCookingRecipeOutputShim(recipe, outputOverride), advancement, conditions); } } -} \ No newline at end of file +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNWashingRecipeGen.java b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNWashingRecipeGen.java index 5854133..6d1b686 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNWashingRecipeGen.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/data/recipe/CNWashingRecipeGen.java @@ -2,6 +2,8 @@ import com.simibubi.create.AllItems; import com.simibubi.create.api.data.recipe.WashingRecipeGen; +import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe; +import com.simibubi.create.content.processing.recipe.StandardProcessingRecipe; import com.tterrag.registrate.util.entry.ItemEntry; import net.minecraft.core.HolderLookup; import net.minecraft.data.PackOutput; @@ -12,6 +14,7 @@ import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; +import java.util.function.UnaryOperator; public class CNWashingRecipeGen extends WashingRecipeGen { @@ -29,4 +32,10 @@ public GeneratedRecipe moddedCrushedOreCustom(ItemEntry crushed, public CNWashingRecipeGen(PackOutput output, CompletableFuture registries) { super(output, registries, CreateNuclear.MOD_ID); } + + @Override + protected GeneratedRecipe create(Supplier singleIngredient, + UnaryOperator> transform) { + return create(CreateNuclear.MOD_ID, singleIngredient, transform); + } } diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/CNClientEvent.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/CNClientEvent.java index 8ba4463..1c2048a 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/CNClientEvent.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/events/CNClientEvent.java @@ -4,20 +4,45 @@ import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.EntityRenderersEvent; import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent; -import net.neoforged.neoforge.client.gui.VanillaGuiLayers; -import net.nuclearteam.createnuclear.CreateNuclear; -import net.nuclearteam.createnuclear.foundation.events.overlay.IrradiatedOverlayRendererVision; +import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent; +import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent; +import net.nuclearteam.createnuclear.*; +import net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorClientExtensions; +import net.nuclearteam.createnuclear.content.particles.NuclearMushroomCloudParticle; +import net.nuclearteam.createnuclear.content.particles.SmallNuclearExplosionParticle; -@EventBusSubscriber(modid = CreateNuclear.MOD_ID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +@EventBusSubscriber(modid = CreateNuclear.MOD_ID, value = Dist.CLIENT) public class CNClientEvent { private static final HudRenderer HUD_RENDERER = new HudRenderer(); @SubscribeEvent public static void onRegisterGui(RegisterGuiLayersEvent event) { HUD_RENDERER.onHudRender(event); - event.registerAbove(VanillaGuiLayers.CAMERA_OVERLAYS, CreateNuclear.asResource("irradiated_vision"), IrradiatedOverlayRendererVision::renderOverlay); } + @SubscribeEvent + public static void onRegisterClientExtensions(RegisterClientExtensionsEvent event) { + AntiRadiationArmorClientExtensions extensions = new AntiRadiationArmorClientExtensions(); + event.registerItem(extensions, + CNItems.ANTI_RADIATION_HELMETS.get(), + CNItems.ANTI_RADIATION_CHESTPLATES.get(), + CNItems.ANTI_RADIATION_LEGGINGS.get(), + CNItems.ANTI_RADIATION_BOOTS.get() + ); + } + + @SubscribeEvent + public static void onRegisterParticleProviders(RegisterParticleProvidersEvent event) { + CNParticleTypes.registerFactories(event); + event.registerSpecial(CNParticleRegistry.NUCLEAR_MUSHROOM_CLOUD.get(), new NuclearMushroomCloudParticle.Factory()); + event.registerSpriteSet(CNParticleRegistry.NUCLEAR_MUSHROOM_CLOUD_SMOKE.get(), SmallNuclearExplosionParticle.NukeFactory::new); + event.registerSpriteSet(CNParticleRegistry.NUCLEAR_MUSHROOM_CLOUD_EXPLOSION.get(), SmallNuclearExplosionParticle.NukeFactory::new); + } + @SubscribeEvent + public static void registerLayers(EntityRenderersEvent.RegisterLayerDefinitions event) { + CNEntityType.registerModelLayer(event); + } } diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/ClientEvents.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/ClientEvents.java new file mode 100644 index 0000000..562daae --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/events/ClientEvents.java @@ -0,0 +1,103 @@ +package net.nuclearteam.createnuclear.foundation.events; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.neoforge.client.event.RenderPlayerEvent; +import net.neoforged.neoforge.client.event.ViewportEvent; +import net.neoforged.neoforge.client.event.ClientTickEvent; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.minecraft.client.model.PlayerModel; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.player.Player; +import net.nuclearteam.createnuclear.CNClientProxy; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem; +import net.nuclearteam.createnuclear.foundation.mixin.client.CameraAccessor; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; + +@EventBusSubscriber(modid = CreateNuclear.MOD_ID, value = Dist.CLIENT) +public class ClientEvents { + + /** + * Ticks down the nuke flash/darken timers, once per client tick. + */ + @SubscribeEvent + public static void onClientTick(ClientTickEvent.Post event) { + + // Store the previous value for smooth interpolation of the flash + CNClientProxy.prevNukeFlashAmount = CNClientProxy.nukeFlashAmount; + + // Count down the sky-darkening timer + if (CNClientProxy.renderNukeSkyDarkFor > 0) { + CNClientProxy.renderNukeSkyDarkFor--; + } + + // Ramp the white flash up while active, then fade it back out + if (CNClientProxy.renderNukeFlashFor > 0) { + if (CNClientProxy.nukeFlashAmount < 1F) { + CNClientProxy.nukeFlashAmount = Math.min(CNClientProxy.nukeFlashAmount + 0.4F, 1F); + } + CNClientProxy.renderNukeFlashFor--; + } else if (CNClientProxy.nukeFlashAmount > 0F) { + CNClientProxy.nukeFlashAmount = Math.max(CNClientProxy.nukeFlashAmount - 0.05F, 0F); + } + } + + /** + * Shakes the player's camera while a nuke explosion is active. + */ + @SubscribeEvent + public static void computeCameraAngles(ViewportEvent.ComputeCameraAngles event) { + Entity player = Minecraft.getInstance().getCameraEntity(); + float partialTick = Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(); + + // Shake at 1.5F while the sky is darkened (nuke active), otherwise no shake + float tremorAmount = CNClientProxy.renderNukeSkyDarkFor > 0 ? 1.5F : 0F; + + if (player != null && CNConfigs.client().screenShaking.get()) { + if (tremorAmount > 0) { + // Generate random offsets for the shake, once per tick + if (CNClientProxy.lastTremorTick != player.tickCount) { + RandomSource rng = player.level().random; + CNClientProxy.randomTremorOffsets[0] = rng.nextFloat(); + CNClientProxy.randomTremorOffsets[1] = rng.nextFloat(); + CNClientProxy.randomTremorOffsets[2] = rng.nextFloat(); + CNClientProxy.lastTremorTick = player.tickCount; + } + + // Scale by Minecraft's screen-effect accessibility setting + double intensity = tremorAmount * Minecraft.getInstance().options.screenEffectScale().get(); + + // Physically offset the camera + ((CameraAccessor) event.getCamera()).callMove( + (float) (CNClientProxy.randomTremorOffsets[0] * 0.2F * intensity), + (float) (CNClientProxy.randomTremorOffsets[1] * 0.2F * intensity), + (float) (CNClientProxy.randomTremorOffsets[2] * 0.5F * intensity) + ); + + } + } + } + + @SubscribeEvent + public static void onRenderPlayerPre(RenderPlayerEvent.Pre event) { + Player player = event.getEntity(); + PlayerModel model = event.getRenderer().getModel(); + + if (player.getItemBySlot(EquipmentSlot.HEAD).getItem() instanceof AntiRadiationArmorItem.Helmet) { + model.hat.visible = false; + } + if (player.getItemBySlot(EquipmentSlot.CHEST).getItem() instanceof AntiRadiationArmorItem.Chestplate) { + model.jacket.visible = false; + model.rightSleeve.visible = false; + model.leftSleeve.visible = false; + } + if (player.getItemBySlot(EquipmentSlot.LEGS).getItem() instanceof AntiRadiationArmorItem.Leggings) { + model.rightPants.visible = false; + model.leftPants.visible = false; + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEventClients.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEventClients.java deleted file mode 100644 index 9e97952..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEventClients.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.nuclearteam.createnuclear.foundation.events; - - -import net.neoforged.api.distmarker.Dist; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.fml.common.EventBusSubscriber.Bus; -import net.neoforged.neoforge.client.event.EntityRenderersEvent; -import net.nuclearteam.createnuclear.CNEntityType; - -@EventBusSubscriber(bus = Bus.MOD, value = Dist.CLIENT) -public class CommentEventClients { - @SubscribeEvent - public static void registerLayers(EntityRenderersEvent.RegisterLayerDefinitions event) { - CNEntityType.registerModelLayer(event); - } - - -} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEvents.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEvents.java index 5f7042d..670694f 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEvents.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEvents.java @@ -1,13 +1,21 @@ package net.nuclearteam.createnuclear.foundation.events; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; import net.neoforged.neoforge.event.brewing.RegisterBrewingRecipesEvent; +import net.neoforged.neoforge.event.entity.EntityAttributeModificationEvent; +import net.neoforged.neoforge.fluids.capability.wrappers.FluidBucketWrapper; +import net.nuclearteam.createnuclear.CNAttributes; +import net.nuclearteam.createnuclear.CNFluids; import net.nuclearteam.createnuclear.CNPotions; import net.nuclearteam.createnuclear.CreateNuclear; -import net.nuclearteam.createnuclear.content.multiblock.input.ReactorInputEntity; +import net.nuclearteam.createnuclear.content.multiblock.input.item.ReactorRodInputEntity; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.ReactorFluidInputEntity; @EventBusSubscriber(modid = CreateNuclear.MOD_ID, bus = EventBusSubscriber.Bus.GAME) public class CommentEvents { @@ -20,8 +28,23 @@ public static void onBrewingRecipeRegister(RegisterBrewingRecipesEvent event) { public static class ModBusEvents { @SubscribeEvent public static void registerCapabilities(RegisterCapabilitiesEvent event) { - ReactorInputEntity.registerCapabilities(event); + ReactorRodInputEntity.registerCapabilities(event); + ReactorFluidInputEntity.registerCapabilities(event); + event.registerItem(Capabilities.FluidHandler.ITEM, + (stack, ctx) -> new FluidBucketWrapper(stack), + CNFluids.URANIUM.get().getBucket()); + } + } + + @EventBusSubscriber(modid = CreateNuclear.MOD_ID, bus = EventBusSubscriber.Bus.MOD) + public static class RadiationEvent { + @SubscribeEvent + public static void onEntityAttribute(EntityAttributeModificationEvent event) { + for (EntityType type : event.getTypes()) { + event.add(type, CNAttributes.IRRADIATED_RESISTANCE); + } } } } + diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/HudRenderer.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/HudRenderer.java index 7eeb910..90fdaf1 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/HudRenderer.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/events/HudRenderer.java @@ -1,7 +1,6 @@ package net.nuclearteam.createnuclear.foundation.events; import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent; -import net.nuclearteam.createnuclear.foundation.events.overlay.EventTextOverlay; import net.nuclearteam.createnuclear.foundation.events.overlay.HelmetOverlay; import net.nuclearteam.createnuclear.foundation.events.overlay.HudOverlay; import net.nuclearteam.createnuclear.foundation.events.overlay.RadiationOverlay; @@ -12,8 +11,7 @@ public class HudRenderer { private static final List overlays = List.of( new HelmetOverlay(), - //new RadiationOverlay(), - new EventTextOverlay() + new RadiationOverlay() ); public void onHudRender(RegisterGuiLayersEvent event) { diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/RodsTooltipHandler.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/RodsTooltipHandler.java new file mode 100644 index 0000000..426baf0 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/events/RodsTooltipHandler.java @@ -0,0 +1,35 @@ +package net.nuclearteam.createnuclear.foundation.events; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.foundation.item.RodsStats; + +@EventBusSubscriber(modid = CreateNuclear.MOD_ID, value = Dist.CLIENT) +public class RodsTooltipHandler { + @SubscribeEvent + public static void onItemTooltip(ItemTooltipEvent event) { + ItemStack stack = event.getItemStack(); + Item item = stack.getItem(); + Player player = event.getEntity(); + + if (player == null) return; + + ResourceLocation id = BuiltInRegistries.ITEM.getKey(item); + // Mod items already get their rod tooltip via Registrate's setTooltipModifierFactory + // (CreateNuclear.REGISTRATE). This handler only serves EXTERNAL items (other mods or + // datapack-defined RodTypes resolved at runtime via RodType.resolveRodType), which + // setTooltipModifierFactory cannot cover. Do NOT remove/invert: doing so double-tooltips mod rods. + if (id != null && CreateNuclear.MOD_ID.equals(id.getNamespace())) return; + + RodsStats rodsStats = RodsStats.create(item); + rodsStats.modify(event); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/EasingHudOverlay.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/EasingHudOverlay.java index 3b2588c..8439a93 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/EasingHudOverlay.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/EasingHudOverlay.java @@ -8,7 +8,7 @@ */ public abstract class EasingHudOverlay implements HudOverlay { private float progress = 0f; - protected float fadeSpeed = 0.03f; + protected float fadeSpeed = 0.01f; @Override public void render(GuiGraphics guiGraphics, DeltaTracker deltaTracker) { diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/EventTextOverlay.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/EventTextOverlay.java deleted file mode 100644 index 4690472..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/EventTextOverlay.java +++ /dev/null @@ -1,65 +0,0 @@ -package net.nuclearteam.createnuclear.foundation.events.overlay; - -import net.minecraft.ChatFormatting; -import net.minecraft.client.DeltaTracker; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.LayeredDraw; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.neoforged.neoforge.client.gui.VanillaGuiLayers; -import net.nuclearteam.createnuclear.CreateNuclear; - -/** - * HUD overlay for displaying localized text when a specific event occurs. - */ -public class EventTextOverlay implements HudOverlay { - private static int timer = 0; - - /** - * Called via a network packet to activate the overlay for a specific duration. - * @param displayDuration duration in ticks - */ - public static void triggerEvent(int displayDuration) { - timer = displayDuration; - } - - @Override - public ResourceLocation getAfterOverlay() { - return VanillaGuiLayers.CAMERA_OVERLAYS; - } - - @Override - public ResourceLocation getOverlayId() { - return ResourceLocation.parse("event_text_overlay"); - } - - @Override - public boolean isActive() { - return timer > 0 && false; - } - - @Override - public void render(GuiGraphics guiGraphics, DeltaTracker deltaTracker) { - if (!isActive()) return; - if (timer-- <= 0) return; - CreateNuclear.LOGGER.warn("hum EventTextOverlay: {}", timer); - LocalPlayer player = Minecraft.getInstance().player; - if (player == null) return; - Component text = Component.translatable("overlay.event_message", timer).withStyle(ChatFormatting.RED); - int widths = guiGraphics.guiWidth(); - int x = (widths - Minecraft.getInstance().font.width(text)) / 2; - guiGraphics.drawString(Minecraft.getInstance().font, text, x, 10, 0xFFFFFF); - } - - @Override - public int getPriority() { - return 300; // render on top of other overlays - } - - @Override - public LayeredDraw.Layer getOverlay() { - return this::render; - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/HelmetOverlay.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/HelmetOverlay.java index 05687a8..95bb333 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/HelmetOverlay.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/HelmetOverlay.java @@ -42,7 +42,7 @@ public boolean isActive() { LocalPlayer player = Minecraft.getInstance().player; if (player == null) return false; ItemStack helmet = player.getInventory().getArmor(EquipmentSlot.HEAD.getIndex()); - return !helmet.isEmpty() && helmet.is(CNItemTags.ANTI_RADIATION_HELMET_FULL_DYE.tag); + return !helmet.isEmpty() && helmet.is(CNItemTags.ANTI_RADIATION_HELMET.tag); } @Override @@ -56,6 +56,7 @@ public void render(GuiGraphics guiGraphics, DeltaTracker deltaTracker) { // Calculate durability ratio float durabilityRatio = (helmet.getMaxDamage() - helmet.getDamageValue()) / (float) helmet.getMaxDamage(); + // Determine texture index based on thresholds int index = durabilityRatio >= 0.95f ? 0 : durabilityRatio >= 0.80f ? 1 diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/IrradiatedOverlayRendererVision.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/IrradiatedOverlayRendererVision.java deleted file mode 100644 index 5ee0a75..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/IrradiatedOverlayRendererVision.java +++ /dev/null @@ -1,107 +0,0 @@ -package net.nuclearteam.createnuclear.foundation.events.overlay; - -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.DeltaTracker; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.LayeredDraw; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.GameType; -import net.nuclearteam.createnuclear.CNEffects; -import net.nuclearteam.createnuclear.CreateNuclear; - -/** - * Handles the client-side rendering of a radiation vision overlay - * when radiation affects the player. - *

- * This class provides a {@link LayeredDraw.Layer} to be injected into GUI overlays, - * and manages the fade-in/fade-out alpha blending of the overlay. - */ -public class IrradiatedOverlayRendererVision { - - /** - * The current transparency level of the irradiated vision overlay. - * This should ideally be tracked per-player but is currently static. - */ - private static float irradiatedVisionAlpha = 0.0f; - - /** - * The texture resource location for the irradiated vision overlay. - */ - public static final ResourceLocation IRRADIATED_VISION = - CreateNuclear.asResource("textures/misc/irradiated_vision/irradiated_vision.png"); - - /** - * Returns a {@link LayeredDraw.Layer} implementation that renders the irradiated vision overlay. - * This method is used to register the overlay with the game's layered renderer system. - * - * @return a Layer that renders the overlay when the radiation effect is active. - */ - public static LayeredDraw.Layer getOverlay() { - return IrradiatedOverlayRendererVision::renderOverlay; - } - - /** - * Renders the overlay if radiation affects the player. - * This method increases or decreases the alpha level based on the presence of the radiation effect. - * It is invoked each frame by the layered GUI system. - * - * @param guiGraphics the GUI graphics context - * @param deltaTracker a tracker for frame delta/time - */ - public static void renderOverlay(GuiGraphics guiGraphics, DeltaTracker deltaTracker) { - Minecraft mc = Minecraft.getInstance(); - - if (mc.options.hideGui || mc.gameMode.getPlayerMode() == GameType.SPECTATOR) - return; - - LocalPlayer localPlayer = mc.player; - RenderSystem.enableBlend(); - - // Adjust the overlay alpha depending on whether the radiation effect is active - if (localPlayer.hasEffect(CNEffects.RADIATION.getDelegate())) { - irradiatedVisionAlpha = Math.min(1.0f, irradiatedVisionAlpha + 0.01f); - } else { - irradiatedVisionAlpha = Math.max(0.0f, irradiatedVisionAlpha - 0.01f); - } - - // Render the overlay if the alpha is greater than 0 - if (irradiatedVisionAlpha > 0.0f) { - renderTextureOverlay(guiGraphics, IRRADIATED_VISION, irradiatedVisionAlpha, true); - } - } - - /** - * Renders a full-screen texture overlay with the specified alpha and rendering conditions. - * - * @param guiGraphics the GUI graphics context - * @param texture the texture to render - * @param alpha the transparency level (0.0 to 1.0) - * @param onlyFirstPerson whether the overlay should only render in first-person view - */ - public static void renderTextureOverlay(GuiGraphics guiGraphics, ResourceLocation texture, float alpha, boolean onlyFirstPerson) { - boolean isFirstPerson = Minecraft.getInstance().options.getCameraType().isFirstPerson(); - - // Skip rendering if restricted to first-person and not in first-person view - if (onlyFirstPerson && !isFirstPerson) - return; - - RenderSystem.disableDepthTest(); - RenderSystem.depthMask(false); - - guiGraphics.setColor(1f, 1f, 1f, alpha); - guiGraphics.blit( - texture, - 0, 0, - -90, - 0.0f, 0.0f, - guiGraphics.guiWidth(), guiGraphics.guiHeight(), - guiGraphics.guiWidth(), guiGraphics.guiHeight() - ); - - RenderSystem.depthMask(true); - RenderSystem.enableDepthTest(); - guiGraphics.setColor(1.0f, 1.0f, 1.0f, 1.0f); - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/RadiationOverlay.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/RadiationOverlay.java index 0b80f4e..d4486bf 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/RadiationOverlay.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/events/overlay/RadiationOverlay.java @@ -1,10 +1,12 @@ package net.nuclearteam.createnuclear.foundation.events.overlay; +import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.LayeredDraw; import net.minecraft.client.player.LocalPlayer; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.GameType; import net.neoforged.neoforge.client.gui.VanillaGuiLayers; import net.nuclearteam.createnuclear.CNEffects; import net.nuclearteam.createnuclear.CreateNuclear; @@ -33,7 +35,7 @@ public ResourceLocation getAfterOverlay() { @Override public ResourceLocation getOverlayId() { - return ResourceLocation.parse("radiation_overlay"); + return CreateNuclear.asResource("radiation_overlay"); } @Override @@ -44,8 +46,28 @@ public boolean isActive() { @Override protected void renderWithAlpha(GuiGraphics graphics, float partialTicks, float alpha) { - // Render radiation overlay with dynamic coverage and alpha - RenderHelper.renderTextureOverlay(graphics, RADIATION_TEXTURE, Math.round(alpha * coverage)); + Minecraft mc = Minecraft.getInstance(); + if (mc.options.hideGui || mc.gameMode == null || mc.gameMode.getPlayerMode() == GameType.SPECTATOR || mc.gameMode.getPlayerMode() == GameType.CREATIVE) + return; + if (!mc.options.getCameraType().isFirstPerson()) + return; + + int width = graphics.guiWidth(); + int height = graphics.guiHeight(); + + graphics.flush(); + RenderSystem.enableBlend(); + RenderSystem.disableDepthTest(); + RenderSystem.depthMask(false); + + graphics.setColor(1f,1f,1f, alpha * coverage); + graphics.blit(RADIATION_TEXTURE, 0, 0, -90, 0, 0, width, height, width, height); + graphics.flush(); + + RenderSystem.depthMask(true); + RenderSystem.enableDepthTest(); + RenderSystem.disableBlend(); + graphics.setColor(1f, 1f, 1f, 1f); } @Override diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/possible code b/src/main/java/net/nuclearteam/createnuclear/foundation/events/possible code deleted file mode 100644 index 87cf86c..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/possible code +++ /dev/null @@ -1,66 +0,0 @@ -/* - * META-INF/services/com.tonpackage.HudOverlay - * ------------------------------------------- - * Liste des implémentations de HudOverlay à charger via ServiceLoader - */ -com.tonpackage.HelmetOverlay -com.tonpackage.PotionOverlay -com.tonpackage.RadiationOverlay - -// -------------------------------------------------------- -package com.tonpackage; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.ServiceLoader; - -/** - * Chargement dynamique de tous les HudOverlay via Java SPI (ServiceLoader) - */ -public class HudOverlayRegistry { - private static final List ALL = new ArrayList<>(); - - static { - ServiceLoader.load(HudOverlay.class) - .forEach(ALL::add); - } - - /** - * Retourne la liste non modifiable de tous les overlays chargés. - */ - public static List getAll() { - return Collections.unmodifiableList(ALL); - } -} - -// -------------------------------------------------------- -package com.tonpackage; - -import net.minecraftforge.client.event.RenderGuiOverlayEvent; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraftforge.client.gui.overlay.VanillaGuiOverlay; - -import java.util.Comparator; - -@Mod.EventBusSubscriber(value = Dist.CLIENT) -public class CNClientEvent { - - @SubscribeEvent - public static void onRenderGuiOverlay(RenderGuiOverlayEvent.Post event) { - // On ne rend qu'après l'overlay "helmet" - if (!event.getOverlay().id().equals(VanillaGuiOverlay.HELMET.id())) return; - - GuiGraphics gfx = event.getGuiGraphics(); - float pt = event.getPartialTick(); - - HudOverlayRegistry.getAll().stream() - .filter(HudOverlay::isActive) - .filter(o -> o.getAfterOverlay().equals(VanillaGuiOverlay.HELMET.id())) - .sorted(Comparator.comparingInt(HudOverlay::getPriority).reversed()) - .forEach(o -> o.render(gfx, pt)); - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/gui/CNGuiTextures.java b/src/main/java/net/nuclearteam/createnuclear/foundation/gui/CNGuiTextures.java index 186543d..4be1ed6 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/gui/CNGuiTextures.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/gui/CNGuiTextures.java @@ -24,19 +24,19 @@ public enum CNGuiTextures implements ScreenElement { public int width, height; public int startX, startY; - private CNGuiTextures(String location, int width, int height) { + CNGuiTextures(String location, int width, int height) { this(location, 0, 0, width, height); } - private CNGuiTextures(int startX, int startY) { + CNGuiTextures(int startX, int startY) { this("icons", startX * 16, startY * 16, 16, 16); } - private CNGuiTextures(String location, int startX, int startY, int width, int height) { + CNGuiTextures(String location, int startX, int startY, int width, int height) { this(CreateNuclear.MOD_ID, location, startX, startY, width, height); } - private CNGuiTextures(String namespace, String location, int startX, int startY, int width, int height) { + CNGuiTextures(String namespace, String location, int startX, int startY, int width, int height) { this.location = ResourceLocation.fromNamespaceAndPath(namespace, "textures/gui/" + location + ".png"); this.width = width; this.height = height; diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/item/DyedItemsList.java b/src/main/java/net/nuclearteam/createnuclear/foundation/item/DyedItemsList.java index 7cc8bbe..d52924a 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/item/DyedItemsList.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/item/DyedItemsList.java @@ -1,10 +1,8 @@ package net.nuclearteam.createnuclear.foundation.item; -import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.ItemEntry; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; import java.util.Arrays; import java.util.Iterator; @@ -13,12 +11,11 @@ public class DyedItemsList implements Iterable> { private static final int COLOR_AMOUNT = DyeColor.values().length; - private final ItemEntry[] values = new ItemEntry[COLOR_AMOUNT]; - public DyedItemsList(Function> filler) { + public DyedItemsList(Function> filter) { for (DyeColor color : DyeColor.values()) { - values[color.ordinal()] = filler.apply(color); + values[color.ordinal()] = filter.apply(color); } } @@ -54,8 +51,7 @@ public boolean hasNext() { @SuppressWarnings("unchecked") @Override public ItemEntry next() { - if (!hasNext()) - throw new NoSuchElementException(); + if (!hasNext()) throw new NoSuchElementException(); return (ItemEntry) values[index++]; } }; diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/item/RodsStats.java b/src/main/java/net/nuclearteam/createnuclear/foundation/item/RodsStats.java new file mode 100644 index 0000000..d17bf13 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/item/RodsStats.java @@ -0,0 +1,65 @@ +package net.nuclearteam.createnuclear.foundation.item; + +import com.simibubi.create.foundation.item.TooltipModifier; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.CommonComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; + +import java.util.ArrayList; +import java.util.List; + +public record RodsStats(Item item) implements TooltipModifier { + + public static RodsStats create(Item item) { + return new RodsStats(item); + } + + @Override + public void modify(ItemTooltipEvent context) { + List rodTypesStat = getRodTypeStats(item, context.getEntity()); + if (!rodTypesStat.isEmpty()) { + List tooltip = context.getToolTip(); + tooltip.add(CommonComponents.EMPTY); + tooltip.addAll(rodTypesStat); + } + } + + private static List getRodTypeStats(Item item, Player player) { + Level world = player.level(); + List components = new ArrayList<>(); + + RodType rodType = RodType.resolveRodType(item, world); + + if (rodType.isNotEmptyItem()) { + CreateNuclearLang.translate("tooltip.statRod") + .style(ChatFormatting.GRAY) + .addTo(components); + + CreateNuclearLang.builder() + .add(CreateNuclearLang.translate("tooltip.baseRodHeat", rodType.baseRodHeat().get())) + .addTo(components); + CreateNuclearLang.builder() + .add(CreateNuclearLang.translate("tooltip.proximityRodHeat", rodType.proximityRodHeat().get())) + .addTo(components); + CreateNuclearLang.builder() + .add(CreateNuclearLang.translate("tooltip.rodTimer", rodType.rodTimer().get())) + .addTo(components); + CreateNuclearLang.builder() + .add(CreateNuclearLang.translate("tooltip.ratio", rodType.ratio().get())) + .addTo(components); + CreateNuclearLang.builder() + .add(CreateNuclearLang.translate("tooltip.typeRod", rodType.type().name())) + .style(rodType.type().equals(RodType.TypeRod.FUEL) ? ChatFormatting.GREEN : ChatFormatting.AQUA) + .addTo(components); + } + + return components; + + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/SmithingTransformRecipeMixin.java b/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/SmithingTransformRecipeMixin.java new file mode 100644 index 0000000..a1a6834 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/SmithingTransformRecipeMixin.java @@ -0,0 +1,35 @@ +package net.nuclearteam.createnuclear.foundation.mixin; + +import net.minecraft.core.HolderLookup; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.SmithingRecipeInput; +import net.minecraft.world.item.crafting.SmithingTransformRecipe; +import net.nuclearteam.createnuclear.CNTags; +import net.nuclearteam.createnuclear.foundation.utility.ClothTagHelper; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(SmithingTransformRecipe.class) +public class SmithingTransformRecipeMixin { + + @Shadow + @Final + ItemStack result; + + @Inject(at = @At("HEAD"), method = "assemble", cancellable = true) + public void CN$assemble(SmithingRecipeInput pInput, HolderLookup.Provider pRegistries, CallbackInfoReturnable cir) { + ItemStack baseItem = pInput.base(); + if (baseItem.is(CNTags.CNItemTags.ANTI_RADIATION_ARMOR.tag)) { + ItemStack resultItem = this.result.copy(); + ItemStack additionItem = pInput.addition(); + + ClothTagHelper.initClothTagsForResult(resultItem, baseItem, additionItem); + + cir.setReturnValue(resultItem); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/AntiRadiationArmorTextureMixin.java b/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/AntiRadiationArmorTextureMixin.java new file mode 100644 index 0000000..b81d05f --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/AntiRadiationArmorTextureMixin.java @@ -0,0 +1,31 @@ +package net.nuclearteam.createnuclear.foundation.mixin.client; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.client.ClientHooks; +import net.nuclearteam.createnuclear.CNDataComponents; +import net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem; +import net.nuclearteam.createnuclear.foundation.utility.ClothTagHelper; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ClientHooks.class) +public class AntiRadiationArmorTextureMixin { + @Inject( + method = "getArmorTexture(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ArmorMaterial$Layer;ZLnet/minecraft/world/entity/EquipmentSlot;)Lnet/minecraft/resources/ResourceLocation;", + at = @At("HEAD"), + cancellable = true + ) + private static void CN$overrideClothTexture(Entity entity, ItemStack stack, ArmorMaterial.Layer layer, + boolean innerModel, EquipmentSlot slot, + CallbackInfoReturnable cir) { + if (stack.getItem() instanceof AntiRadiationArmorItem && stack.has(CNDataComponents.CLOTH_COLOR)) { + cir.setReturnValue(ClothTagHelper.getArmorTexturePath(stack, "anti_radiation_suit.png")); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/CameraAccessor.java b/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/CameraAccessor.java new file mode 100644 index 0000000..fed57d9 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/CameraAccessor.java @@ -0,0 +1,12 @@ +package net.nuclearteam.createnuclear.foundation.mixin.client; + +import net.minecraft.client.Camera; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Camera.class) +public interface CameraAccessor { + // Exposes the private Camera#move so it can be called from outside the class + @Invoker("move") + void callMove(float distanceOffset, float verticalOffset, float horizontalOffset); +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/GameRendererMixin.java b/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/GameRendererMixin.java new file mode 100644 index 0000000..4e4b1b6 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/GameRendererMixin.java @@ -0,0 +1,43 @@ +package net.nuclearteam.createnuclear.foundation.mixin.client; + +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.renderer.GameRenderer; +import net.nuclearteam.createnuclear.CNClientProxy; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GameRenderer.class) +public abstract class GameRendererMixin { + + @Shadow + private float darkenWorldAmount; + + // Handles darkening the sky/world during a nuclear explosion + @Inject( + method = {"Lnet/minecraft/client/renderer/GameRenderer;tick()V"}, + remap = true, + at = @At(value = "TAIL") + ) + public void CN$tick(CallbackInfo ci) { + if (CNClientProxy.renderNukeSkyDarkFor > 0 && darkenWorldAmount < 1.0F) { + darkenWorldAmount = Math.min(darkenWorldAmount + 0.3F, 1.0F); + } + } + + // Triggers the white flash render (preScreenRender) + @Inject( + method = {"Lnet/minecraft/client/renderer/GameRenderer;render(Lnet/minecraft/client/DeltaTracker;Z)V"}, + remap = true, + at = @At( + value = "INVOKE", + target = "Lcom/mojang/blaze3d/platform/Lighting;setupFor3DItems()V", + shift = At.Shift.AFTER + ) + ) + public void CN$render(DeltaTracker deltaTracker, boolean renderLevel, CallbackInfo ci) { + CNClientProxy.preScreenRender(deltaTracker.getGameTimeDeltaPartialTick(false)); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/RadiationHeartMixin.java b/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/RadiationHeartMixin.java new file mode 100644 index 0000000..a39870b --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/mixin/client/RadiationHeartMixin.java @@ -0,0 +1,40 @@ +package net.nuclearteam.createnuclear.foundation.mixin.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.nuclearteam.createnuclear.CNEffects; +import net.nuclearteam.createnuclear.CreateNuclear; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +@Mixin(Gui.class) +public class RadiationHeartMixin { + + @ModifyArg( + method = "renderHeart", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/gui/GuiGraphics;blitSprite(Lnet/minecraft/resources/ResourceLocation;IIII)V" + ), + index = 0 + ) + private ResourceLocation CN$changeHeartTexture(ResourceLocation originalTexture) { + Player player = Minecraft.getInstance().player; + + if (player != null && player.hasEffect(CNEffects.RADIATION)) { + String path = originalTexture.getPath(); + if (originalTexture.getNamespace().equals("minecraft") && path.startsWith("hud/heart/")) { + String heartType = path.substring("hud/heart/".length()); + String baseType = heartType.replace("_blinking", ""); + + if (baseType.equals("full") || baseType.equals("half") || baseType.equals("hardcore_full") || baseType.equals("hardcore_half")) { + return CreateNuclear.asResource("hud/heart/radiation_" + baseType); + } + } + } + return originalTexture; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CNPonderIndex.java b/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CNPonderIndex.java index 3ded587..582bf4c 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CNPonderIndex.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CNPonderIndex.java @@ -1,29 +1,29 @@ package net.nuclearteam.createnuclear.foundation.ponder; - import com.tterrag.registrate.util.entry.ItemProviderEntry; import com.tterrag.registrate.util.entry.RegistryEntry; import net.createmod.ponder.api.registration.PonderSceneRegistrationHelper; import net.minecraft.resources.ResourceLocation; import net.nuclearteam.createnuclear.CNBlocks; import net.nuclearteam.createnuclear.CNItems; - +import net.nuclearteam.createnuclear.infrastructure.ponder.scenes.CNPonderReactorScenes; public class CNPonderIndex { public static void register(PonderSceneRegistrationHelper helper) { PonderSceneRegistrationHelper> HELPER = helper.withKeyFunction(RegistryEntry::getId); - // Reactor + // Reactor - Storyboards pour chaque taille HELPER.forComponents(CNBlocks.REACTOR_CONTROLLER) - .addStoryBoard("reactor/setup", CNPonderReactor::init) - .addStoryBoard("reactor/setup", CNPonderReactor::enable); - + .addStoryBoard("reactor/reactor_t1_ponder", CNPonderReactorScenes::t1) + .addStoryBoard("reactor/reactor_t2_ponder", CNPonderReactorScenes::t2) + .addStoryBoard("reactor/reactor_t3_ponder", CNPonderReactorScenes::t3) + .addStoryBoard("reactor/reactor_t1_ponder", CNPonderReactorScenes::ioPlacement); HELPER.forComponents(CNItems.REACTOR_BLUEPRINT) - .addStoryBoard("reactor/setup", CNPonderReactor::enable); - - ; - + .addStoryBoard("reactor/reactor_t1_ponder", CNPonderReactorScenes::t1) + .addStoryBoard("reactor/reactor_t2_ponder", CNPonderReactorScenes::t2) + .addStoryBoard("reactor/reactor_t3_ponder", CNPonderReactorScenes::t3) + .addStoryBoard("reactor/reactor_t1_ponder", CNPonderReactorScenes::ioPlacement); } } \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CNPonderReactor.java b/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CNPonderReactor.java deleted file mode 100644 index 4436ba4..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CNPonderReactor.java +++ /dev/null @@ -1,103 +0,0 @@ -package net.nuclearteam.createnuclear.foundation.ponder; - -import net.createmod.catnip.math.Pointing; -import net.createmod.ponder.api.scene.SceneBuilder; -import net.createmod.ponder.api.scene.SceneBuildingUtil; -import net.createmod.ponder.foundation.element.InputWindowElement; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.nuclearteam.createnuclear.CNItems; -import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock; - -public class CNPonderReactor { - - private static final BlockPos CONTROLLER = new BlockPos(4, 4, 6); - private static final BlockPos OUTPUT = new BlockPos(4, 1, 6); - private static final BlockPos INPUT = new BlockPos(4, 4, 2); - public static void init(SceneBuilder scene, SceneBuildingUtil util) { - scene.title("reactor", "Construction of the reactor"); - scene.configureBasePlate(0,0,9); - scene.showBasePlate(); - - - for (int y = 1; y < 8; y++) { - scene.overlay().showText(10) - .text("Floor " + y) - .attachKeyFrame() - .placeNearTarget(); - - for (int x = 1; x < 7; x++) { - for (int z = 1; z < 7; z++) { - scene.world().showSection(util.select().position(x,y,z), Direction.NORTH); - scene.idle(5); - if (x == 5 && z == 5 && y == 1) { - scene.rotateCameraY(180f); - } - if (x == INPUT.getX() && y == INPUT.getY() && z == INPUT.getZ()) { - scene.rotateCameraY(180f); - scene.overlay().showText(90) - .text("Reactor Input: A block that stores uranium and graphite rods to operate the reactor.") - .pointAt(util.vector().blockSurface(INPUT, Direction.UP)) - .attachKeyFrame() - .placeNearTarget(); - scene.idle(120); - scene.rotateCameraY(180f); - } - if (x == OUTPUT.getX() && y == OUTPUT.getY() && z == OUTPUT.getZ()) { - //AABB bb = new AABB(OUTPUT).inflate(1/16f, 0, 0); - scene.overlay().showText(90) - .text("Reactor Output: This is the block that outputs the energy (SU) generated by the reactor.") - .pointAt(util.vector().blockSurface(OUTPUT, Direction.UP)) - .attachKeyFrame() - .placeNearTarget(); - scene.idle(120); - } - if (x == CONTROLLER.getX() && y == CONTROLLER.getY() && z == CONTROLLER.getZ()){ - scene.overlay().showText(90) - .text("Reactor Controller: The most important block to operate the reactor; it handles all the calculations needed to generate power.") - .pointAt(util.vector().blockSurface(CONTROLLER, Direction.DOWN)) - .attachKeyFrame() - .placeNearTarget(); - scene.idle(120); - } - } - } - - } - } - - public static void enable(SceneBuilder scene, SceneBuildingUtil util) { - scene.title("reactor_blueprint", "Controller Activation"); - scene.configureBasePlate(0,0,9); - scene.world().showSection(util.select().layer(0), Direction.UP); - scene.showBasePlate(); - - scene.rotateCameraY(260f); - for (int y = 1; y < 8; y++) { - for (int x = 1; x < 7; x++) { - for (int z = 1; z < 7; z++) { - scene.world().showSection(util.select().position(x,y,z), Direction.NORTH); - } - } - } - // For more details, refer to the item's tooltip. - scene.idle(30); - scene.overlay() - .showText(90) - .text("Reactor Blueprint: the most important element; it allows the reactor to be configured according to specific models."); - - Vec3 topSide = util.vector().blockSurface(CONTROLLER, Direction.EAST); - - - scene.overlay() - .showControls(topSide, Pointing.UP, 90) - .withItem(CNItems.REACTOR_BLUEPRINT.asStack()) - .rightClick() - ; - - - scene.world().modifyBlock(CONTROLLER, s -> s.setValue(ReactorControllerBlock.ASSEMBLED, true), true); - } -} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CreateNuclearPonderPlugin.java b/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CreateNuclearPonderPlugin.java index 3172b1b..ef09769 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CreateNuclearPonderPlugin.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CreateNuclearPonderPlugin.java @@ -5,6 +5,7 @@ import net.createmod.ponder.api.registration.PonderTagRegistrationHelper; import net.minecraft.resources.ResourceLocation; import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.infrastructure.ponder.CNCreateNuclearPonderTags; public class CreateNuclearPonderPlugin implements PonderPlugin { @Override diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/utility/ClothTagHelper.java b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/ClothTagHelper.java new file mode 100644 index 0000000..aecb375 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/ClothTagHelper.java @@ -0,0 +1,43 @@ +package net.nuclearteam.createnuclear.foundation.utility; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.nuclearteam.createnuclear.CNDataComponents; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.equipment.cloth.ClothItem; +import net.nuclearteam.createnuclear.content.equipment.cloth.ClothItem.ClothItemStack; +import net.nuclearteam.createnuclear.content.equipment.cloth.ClothItem.Cloths; + +public final class ClothTagHelper { + private ClothTagHelper() {} + + public static void initClothTagsForResult(ItemStack resultItem, ItemStack baseItem, ItemStack additionItem) { + if (!resultItem.has(CNDataComponents.CLOTH_COLOR) && baseItem.has(CNDataComponents.CLOTH_COLOR)) { + resultItem.set(CNDataComponents.CLOTH_COLOR, baseItem.get(CNDataComponents.CLOTH_COLOR)); + } + + if (!resultItem.has(CNDataComponents.CLOTH_ITEM) && baseItem.has(CNDataComponents.CLOTH_ITEM)) { + resultItem.set(CNDataComponents.CLOTH_ITEM, baseItem.get(CNDataComponents.CLOTH_ITEM)); + } + + if (additionItem != null && additionItem.getItem() instanceof ClothItem clothItem) { + resultItem.set(CNDataComponents.CLOTH_COLOR, Cloths.of(clothItem.getColor())); + resultItem.set(CNDataComponents.CLOTH_ITEM, new ClothItemStack(additionItem.copy())); + } + } + + public static DyeColor getClothColor(ItemStack stack, DyeColor defaultColor) { + if (stack == null) return defaultColor; + Cloths cloth = stack.get(CNDataComponents.CLOTH_COLOR); + DyeColor color = cloth != null ? cloth.getDyeColor() : null; + return color != null ? color : defaultColor; + } + + public static ResourceLocation getArmorTexturePath(ItemStack stack, String armorFileName) { + DyeColor color = getClothColor(stack, null); + String prefix = color != null ? color.getSerializedName() : "default"; + String textureFile = prefix + "_" + armorFileName; + return CreateNuclear.asResource("textures/models/armor/" + textureFile); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/utility/ConfigValueResolver.java b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/ConfigValueResolver.java new file mode 100644 index 0000000..8829716 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/ConfigValueResolver.java @@ -0,0 +1,57 @@ +package net.nuclearteam.createnuclear.foundation.utility; + +import net.nuclearteam.createnuclear.CreateNuclear; + +import java.util.Collection; +import java.util.Set; +import java.util.function.Function; + +/** + * Utility class for resolving and loading configuration values into a target set. + *

+ * This class provides a static method to map a collection of input values to a set of resolved values, + * using a provided resolver function. It handles errors and logs unknown or invalid values. + *

+ */ +public final class ConfigValueResolver { + private ConfigValueResolver() {} + + /** + * Loads and resolves values from a collection into a target set using the provided resolver function. + *

+ * The target set is cleared before loading. For each value in the input collection, the resolver function is applied. + * If the resolved value is not null, it is added to the target set. If the value is unknown or an exception occurs, + * an error is logged. + *

+ * + * Usage example: + *
+     * Set mySet = new HashSet<>();
+     * List configValues = Arrays.asList("A", "B", "C");
+     * ConfigValueResolver.loadValuesInSet(configValues, mySet, MyType::fromString);
+     * 
+ * + * @param values the collection of input values to resolve + * @param targetSet the set to populate with resolved values (will be cleared first) + * @param resolver the function to resolve each input value to the target type + * @param the input value type + * @param the target value type + */ + public static void loadValuesInSet(Collection values, Set targetSet, Function resolver) { + targetSet.clear(); + + for (I valueId : values) { + try { + T value = resolver.apply(valueId); + + if (value != null) { + targetSet.add(value); + } else { + CreateNuclear.LOGGER.error("Unknown value in config: {}", valueId); + } + } catch (Exception e) { + CreateNuclear.LOGGER.error("Unknown value in config: {} - {}", valueId, e.getMessage()); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/utility/InventoryHashUtil.java b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/InventoryHashUtil.java new file mode 100644 index 0000000..ba04bd1 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/InventoryHashUtil.java @@ -0,0 +1,95 @@ +package net.nuclearteam.createnuclear.foundation.utility; + +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +/** + * Utility class for computing a compact long-valued hash that represents a + * {@link net.minecraft.world.entity.player.Player Player}'s inventory state. + * + *

The hash aggregates contributions from the player's main inventory, offhand + * slots, and armor slots. It is intended for fast change-detection, caching, + * or lightweight synchronization checks where a compact fingerprint is useful. + * This is not a cryptographic checksum and may collide for + * different inventories.

+ * + *

Implementation details: + * - Empty stacks contribute {@code 0}. + * - Each non-empty stack contributes a value computed from the numeric item id, + * stack count, and the NBT tag's {@code hashCode()} when present. Damage value + * is intentionally excluded: no radiation source reads it, so including it would + * only cause needless recomputation on every durability change. + * - Per-stack contributions are combined using a 31-multiplicative rolling scheme + * (similar to {@link String#hashCode()}).

+ * + *

Thread-safety: this class is stateless. Calling code must ensure the + * {@link Player} instance is not concurrently mutated if callers require + * perfectly consistent snapshots.

+ */ +public class InventoryHashUtil { + /** + * Computes a deterministic long value representing the contents of the + * provided player's inventory. + * + *

The method iterates the player's main inventory slots ({@code + * player.getInventory().items}), offhand slots ({@code + * player.getInventory().offhand}) and armor slots ({@code + * player.getArmorSlots()}) and combines each stack's contribution using a + * simple rolling scheme. Equal return values usually indicate identical + * inventory contents, but different inventories can collide.

+ * + * @param player the player whose inventory will be hashed; must not be + * {@code null} + * @return a long value derived from the contents of the player's + * inventory. This value is suitable for quick equality/change + * detection but is not collision-resistant. + * @throws NullPointerException if {@code player} is {@code null} + * @implNote The algorithm uses {@link Item#getId(net.minecraft.world.item.Item)} + * and basic stack properties (count, tag.hashCode()). It is + * intentionally simple and optimized for speed rather than + * cryptographic strength. + */ + public static long compute(Player player) { + long hash = 1; + + for (ItemStack stack : player.getInventory().items) { + hash = 31 * hash + stackHash(stack); + } + + for (ItemStack stack : player.getInventory().offhand) { + hash = 31 * hash + stackHash(stack); + } + + for (ItemStack stack : player.getArmorSlots()) { + hash = 31 * hash + stackHash(stack); + } + + return hash; + } + + /** + * Computes the contribution of a single {@link ItemStack} to the overall + * inventory hash. + * + *

Empty stacks return {@code 0}. For non-empty stacks the returned value + * encodes the numeric item id, the stack count, and, when applicable, the + * NBT tag's {@code hashCode()}.

+ * + * @param stack the item stack to hash; must not be {@code null} + * @return a {@code long} representing the stack's contribution; {@code 0} + * for empty stacks + * @throws NullPointerException if {@code stack} is {@code null} + * @see #compute(Player) + */ + private static long stackHash(ItemStack stack) { + if (stack.isEmpty()) return 0; + + long h = Item.getId(stack.getItem()); + h = 31 * h + stack.getCount(); + + h = 31 * h + stack.getComponents().hashCode(); + + return h; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/utility/Maths.java b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/Maths.java new file mode 100644 index 0000000..97c4693 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/Maths.java @@ -0,0 +1,147 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package net.nuclearteam.createnuclear.foundation.utility; + +import com.google.common.collect.Sets; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Holder; +import net.minecraft.core.QuartPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.levelgen.synth.SimplexNoise; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeSource; +import net.minecraft.world.level.biome.Climate; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.BooleanOp; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class Maths { + public static final Direction[] HORIZONTAL_DIRECTIONS; + public static final Direction[] NOT_UP_DIRECTIONS; + public static final float HALF_SQRT_3; + public static final float QUARTER_PI = 0.7853982F; + + public Maths() { + } + + private static final SimplexNoise NOISE = new SimplexNoise(RandomSource.create(0)); + + public static float smin(float a, float b, float k) { + float h = Math.max(k - Math.abs(a - b), 0.0F) / k; + return Math.min(a, b) - h * h * k * 0.25F; + } + + public static float sampleNoise2D(int x, int z, float simplexSampleRate) { + return (float) NOISE.getValue((((float)x + simplexSampleRate) / simplexSampleRate), (((float)z + simplexSampleRate) / simplexSampleRate)); + } + + public static float sampleNoise3D(int x, int y, int z, float simplexSampleRate) { + return (float) NOISE.getValue((((float)x + simplexSampleRate) / simplexSampleRate), (((float)y + simplexSampleRate) / simplexSampleRate), (((float)z + simplexSampleRate) / simplexSampleRate)); + } + + public static float sampleNoise3D(float x, float y, float z, float simplexSampleRate) { + return (float) NOISE.getValue(((x + simplexSampleRate) / simplexSampleRate), ((y + simplexSampleRate) / simplexSampleRate), ((z + simplexSampleRate) / simplexSampleRate)); + } + + public static VoxelShape buildShape(VoxelShape... from) { + return (VoxelShape)Stream.of(from).reduce((v1, v2) -> { + return Shapes.join(v1, v2, BooleanOp.OR); + }).get(); + } + + public static float walkValue(float limbSwing, float limbSwingAmount, float speed, float offset, float degree, boolean inverse) { + return (float)(Math.cos((double)(limbSwing * speed + offset)) * (double)degree * (double)limbSwingAmount * (double)(inverse ? -1 : 1)); + } + + public static float approachRotation(float current, float target, float max) { + float f = Mth.wrapDegrees(target - current); + if (f > max) { + f = max; + } + + if (f < -max) { + f = -max; + } + + return Mth.wrapDegrees(current + f); + } + + public static Vec3 getGroundBelowPosition(BlockGetter level, Vec3 in) { + BlockPos pos; + for(pos = BlockPos.containing(in); pos.getY() > level.getMinBuildHeight() && level.getBlockState(pos).getCollisionShape(level, pos).isEmpty(); pos = pos.below()) { + } + + BlockState state = level.getBlockState(pos); + VoxelShape shape = state.getCollisionShape(level, pos); + float top; + if (shape.isEmpty()) { + top = 0.0F; + } else { + Vec3 modIn = new Vec3(in.x % 1.0, 1.0, in.z % 1.0); + Optional closest = shape.closestPointTo(modIn); + top = closest.isPresent() ? (float)((Vec3)closest.get()).y : 0.0F; + } + + return Vec3.upFromBottomCenterOf(pos, (double)top); + } + + public static Vec3 readVec3(FriendlyByteBuf buf) { + return new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()); + } + + public static FriendlyByteBuf writeVec3(FriendlyByteBuf buf, Vec3 vec3) { + buf.writeDouble(vec3.x()); + buf.writeDouble(vec3.y()); + buf.writeDouble(vec3.z()); + return buf; + } + + public static float approachDegreesNoWrap(float from, float to, float by) { + float f = (to - from) % 360.0F; + return Mth.approach(from, from + f, by); + } + + public static float canyonStep(float heightScale, int scaleTo) { + int clampTo100 = (int)(heightScale * (float)scaleTo * (float)scaleTo); + return Mth.clamp((float)Math.round((float)clampTo100 / (float)scaleTo) / (float)scaleTo, 0.0F, 1.0F); + } + + public static Set> getBiomesWithinAtY(BiomeSource biomeSource, int x, int y, int z, int xzDist, Climate.Sampler sampler) { + int i = QuartPos.fromBlock(x - xzDist); + int j = QuartPos.fromBlock(y); + int k = QuartPos.fromBlock(z - xzDist); + int l = QuartPos.fromBlock(x + xzDist); + int j1 = QuartPos.fromBlock(z + xzDist); + int k1 = l - i + 1; + int i2 = j1 - k + 1; + Set> set = Sets.newHashSet(); + + for(int j2 = 0; j2 < i2; ++j2) { + for(int k2 = 0; k2 < k1; ++k2) { + int i3 = i + k2; + int k3 = k + j2; + set.add(biomeSource.getNoiseBiome(i3, j, k3, sampler)); + } + } + + return set; + } + + static { + HORIZONTAL_DIRECTIONS = new Direction[]{Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; + NOT_UP_DIRECTIONS = new Direction[]{Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.DOWN}; + HALF_SQRT_3 = (float)(Math.sqrt(3.0) / 2.0); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/utility/NotifyUtil.java b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/NotifyUtil.java new file mode 100644 index 0000000..d712be2 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/NotifyUtil.java @@ -0,0 +1,155 @@ +package net.nuclearteam.createnuclear.foundation.utility; + +import net.createmod.catnip.lang.LangBuilder; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket; +import net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket; +import net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Utility class for sending player notifications server-side. + * Supports Action Bar messages and full-screen title/subtitle overlays, + * with radius-based or server-wide targeting. + */ +public class NotifyUtil { + + /** + * Convenience overload that accepts a {@link LangBuilder} message, + * converting it to a {@link MutableComponent} before sending. + * + * @see #sendActionBar(Level, BlockPos, MutableComponent, ChatFormatting, int, boolean) + */ + public static void sendActionBar(Level level, BlockPos pos, LangBuilder message, ChatFormatting color, int radius, boolean warnAll) { + sendActionBar(level, pos, message.component(), color, radius, warnAll); + } + + /** + * Sends a bold colored message to the Action Bar (above the hotbar) of nearby players. + * No-ops on the client side. + * + * @param level The server-side world used to resolve players + * @param pos Center position used to compute the notification radius + * @param message The component text to display; will be styled bold with {@code color} + * @param color {@link ChatFormatting} color applied to the message + * @param radius Block radius around {@code pos} within which players are notified; + * ignored when {@code warnAll} is {@code true} + * @param warnAll If {@code true}, all online players receive the message regardless of position + */ + public static void sendActionBar(Level level, BlockPos pos, MutableComponent message, ChatFormatting color, int radius, boolean warnAll) { + if (level.isClientSide) return; + + // Build the text component in BOLD with the chosen color + Component actionBarComp = message.withStyle(color, ChatFormatting.BOLD); + + List targets = getTargetPlayers(level, pos, radius, warnAll); + + for (ServerPlayer player : targets) { + // The 'true' parameter routes the message to the Action Bar + player.displayClientMessage(actionBarComp, true); + } + } + + /** + * Convenience overload that accepts {@link LangBuilder} title and subtitle, + * converting them to {@link MutableComponent} before sending. + * + * @see #sendTitle(Level, BlockPos, MutableComponent, MutableComponent, ChatFormatting, int, boolean, int, int, int) + */ + public static void sendTitle(Level level, BlockPos pos, LangBuilder title, LangBuilder subtitle, ChatFormatting color, + int radius, boolean warnAll, int fadeIn, int stay, int fadeOut) { + sendTitle(level, pos, title.component(), subtitle.component(), color, radius, warnAll, fadeIn, stay, fadeOut); + } + + /** + * Sends a full-screen title and subtitle overlay to nearby players. + * The title is rendered bold with {@code color}; the subtitle is always white. + * No-ops on the client side. + * + * @param level The server-side world used to resolve players + * @param pos Center position used to compute the notification radius + * @param title Main title text displayed in large letters + * @param subtitle Subtitle text displayed below the title + * @param color {@link ChatFormatting} color applied to the title + * @param radius Block radius around {@code pos} within which players are notified; + * ignored when {@code warnAll} is {@code true} + * @param warnAll If {@code true}, all online players receive the message regardless of position + * @param fadeIn Ticks for the fade-in animation + * @param stay Ticks the title remains fully visible + * @param fadeOut Ticks for the fade-out animation + */ + public static void sendTitle(Level level, BlockPos pos, MutableComponent title, MutableComponent subtitle, ChatFormatting color, + int radius, boolean warnAll, int fadeIn, int stay, int fadeOut) { + + if (level.isClientSide) return; + + Component titleComp = title.withStyle(color, ChatFormatting.BOLD); + Component subtitleComp = subtitle.withStyle(ChatFormatting.WHITE); + + List targets = getTargetPlayers(level, pos, radius, warnAll); + + for (ServerPlayer serverPlayer : targets) { + serverPlayer.connection.send(new ClientboundSetTitlesAnimationPacket(fadeIn, stay, fadeOut)); + serverPlayer.connection.send(new ClientboundSetSubtitleTextPacket(subtitleComp)); + serverPlayer.connection.send(new ClientboundSetTitleTextPacket(titleComp)); + } + } + + /** + * Convenience overload that accepts {@link LangBuilder} title and subtitle, + * converting them to {@link MutableComponent} before sending. + * + * @see #quickAlert(Level, BlockPos, MutableComponent, MutableComponent, ChatFormatting, int, boolean) + */ + public static void quickAlert(Level level, BlockPos pos, LangBuilder title, LangBuilder sub, ChatFormatting color, int radius, boolean warnAll) { + quickAlert(level, pos, title.component(), sub.component(), color, radius, warnAll); + } + + + /** + * Shortcut for {@link #sendTitle} using default animation timings (fadeIn=10, stay=50, fadeOut=10). + * + * @param level The server-side world used to resolve players + * @param pos Center position used to compute the notification radius + * @param title Main title text + * @param sub Subtitle text + * @param color {@link ChatFormatting} color applied to the title + * @param radius Block radius around {@code pos}; ignored when {@code warnAll} is {@code true} + * @param warnAll If {@code true}, all online players receive the message + */ + public static void quickAlert(Level level, BlockPos pos, MutableComponent title, MutableComponent sub, ChatFormatting color, int radius, boolean warnAll) { + sendTitle(level, pos, title, sub, color, radius, warnAll, 10, 50, 10); + } + + /** + * Resolves the list of players to notify. + * Returns all online players if {@code warnAll} is {@code true}, + * otherwise returns only those within {@code radius} blocks of {@code pos}. + * + * @param level The server-side world + * @param pos Center position for the radius check + * @param radius Block radius for proximity filtering + * @param warnAll If {@code true}, bypasses the radius check + * @return Mutable list of matching {@link ServerPlayer} instances; empty if the server is unavailable + */ + private static List getTargetPlayers(Level level, BlockPos pos, int radius, boolean warnAll) { + if (level.getServer() == null) return List.of(); + + List allPlayers = level.getServer().getPlayerList().getPlayers(); + if (warnAll) return new ArrayList<>(allPlayers); + + AABB area = new AABB(pos).inflate(radius); + return allPlayers.stream() + .filter(p -> area.contains(p.getX(), p.getY(), p.getZ())) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/utility/RenderHelper.java b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/RenderHelper.java index 969c054..740478d 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/utility/RenderHelper.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/utility/RenderHelper.java @@ -42,6 +42,8 @@ public static void renderOverlay(GuiGraphics graphics, ResourceLocation texture, graphics.setColor(1f, 1f, 1f, alpha); RenderSystem.enableBlend(); + RenderSystem.depthMask(false); + RenderSystem.disableDepthTest(); if (coverage != 1f) { // Center + scale @@ -58,6 +60,8 @@ public static void renderOverlay(GuiGraphics graphics, ResourceLocation texture, graphics.blit(texture, 0, 0, -90, 0, 0, width, height, width, height); } + RenderSystem.enableDepthTest(); + RenderSystem.depthMask(true); RenderSystem.disableBlend(); } diff --git a/src/main/java/net/nuclearteam/createnuclear/gametest/DefaultHeatCalculatorGameTest.java b/src/main/java/net/nuclearteam/createnuclear/gametest/DefaultHeatCalculatorGameTest.java new file mode 100644 index 0000000..fdd8a74 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/gametest/DefaultHeatCalculatorGameTest.java @@ -0,0 +1,368 @@ +package net.nuclearteam.createnuclear.gametest; + +import io.netty.buffer.Unpooled; +import net.minecraft.core.BlockPos; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestAssertException; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.nbt.Tag; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.CNDataComponents; +import net.nuclearteam.createnuclear.CNItems; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.PatternData; +import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintData; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerInventory; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; +import net.nuclearteam.createnuclear.content.multiblock.reactorLogic.DefaultHeatCalculator; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; + +import java.util.List; +import java.util.Map; + +/** + * GameTest coverage for {@link DefaultHeatCalculator#computeHeat}, run against a real + * {@code ServerLevel}, a real {@link ReactorControllerBlockEntity} and real registered + * rod items (no mocks) — plain JUnit cannot exercise this method at all: {@code Item}, + * {@code ItemStack} and {@code RodType} resolution all depend on Minecraft/NeoForge registries + * that only exist once the game has bootstrapped. + *

+ * All tests share the "empty_platform" structure and place a single + * {@code CNBlocks.REACTOR_CONTROLLER} to obtain a real {@link ReactorControllerInventory}. + * The reactor pattern (57 slots, indices per {@code DefaultHeatCalculator.FORMATTED_PATTERN}) + * is written into the blueprint's {@link ReactorBluePrintData} component and set into inventory + * slot 0, exactly as {@code ReactorBluePrintItem.getItemStorage} reads it back. + *

+ * This is where the port diverges from Forge: Forge writes the pattern into the blueprint's + * raw {@code pattern} NBT tag, which has no NeoForge equivalent since the blueprint carries a + * typed data component instead. + *

+ * Expected heat values are computed from the live {@code CNConfigs.server().rods} values + * rather than hardcoded, so these tests stay correct if the mod's default balance changes. + */ +@GameTestHolder(CreateNuclear.MOD_ID) +@PrefixGameTestTemplate(false) +public class DefaultHeatCalculatorGameTest { + + private static final String STRUCTURE = "empty_platform"; + private static final double DELTA = 1e-9; + private static final int PATTERN_SLOTS = 57; + + // ---------- test fixtures ---------- + + private static ReactorControllerInventory placeController(GameTestHelper helper, BlockPos rel) { + helper.setBlock(rel, CNBlocks.REACTOR_CONTROLLER.get().defaultBlockState()); + ReactorControllerBlockEntity be = (ReactorControllerBlockEntity) helper.getBlockEntity(rel); + return be.getInventoryObject(); + } + + /** + * Writes {@code rodsBySlot} into the blueprint's {@link ReactorBluePrintData} component and + * loads it into slot 0. Every one of the 57 slots must be present, since + * {@code ReactorBluePrintItem.getItemStorage} bails out on a shorter array. + */ + private static void loadPattern(ReactorControllerInventory inventory, Map rodsBySlot) { + inventory.setStackInSlot(0, buildBlueprint(rodsBySlot)); + } + + /** Builds the blueprint {@link #loadPattern} loads, without touching an inventory. */ + private static ItemStack buildBlueprint(Map rodsBySlot) { + PatternData[] pattern = new PatternData[PATTERN_SLOTS]; + for (int slot = 0; slot < PATTERN_SLOTS; slot++) { + Item rod = rodsBySlot.get(slot); + pattern[slot] = new PatternData(slot, rod == null ? ItemStack.EMPTY : new ItemStack(rod)); + } + + ItemStack blueprint = new ItemStack(CNItems.REACTOR_BLUEPRINT.get()); + blueprint.set(CNDataComponents.REACTOR_BLUE_PRINT_DATA, + new ReactorBluePrintData(0, 0, pattern)); + return blueprint; + } + + private static final DefaultHeatCalculator CALCULATOR = new DefaultHeatCalculator(); + + // ================================================================ + // 0. the heat component must survive being saved at zero + // ================================================================ + + /** + * Regression test for a world-save crash: {@code CNDataComponents.HEAT} was registered with + * {@code ExtraCodecs.POSITIVE_FLOAT}, which rejects {@code 0.0}. The controller writes the + * heat on every tick, so as soon as a blueprint sat in a stopped reactor the chunk save blew + * up with "Value must be positive: 0.0" and the block entity silently stopped persisting. + *

+ * A persistent codec that can refuse a value fails at save time, not at write time, which is + * why this is asserted here rather than left to the non-negative floor in + * {@link DefaultHeatCalculator#computeHeat}. + */ + @GameTest(template = STRUCTURE) + public static void heatComponent_atZero_survivesSerialization(GameTestHelper helper) { + ItemStack blueprint = new ItemStack(CNItems.REACTOR_BLUEPRINT.get()); + blueprint.set(CNDataComponents.HEAT, 0f); + + var registries = helper.getLevel().registryAccess(); + Tag saved; + try { + saved = blueprint.save(registries); + } catch (RuntimeException e) { + throw new GameTestAssertException( + "a blueprint carrying heat=0 must be serializable, got: " + e.getMessage()); + } + + ItemStack restored = ItemStack.parse(registries, saved).orElse(ItemStack.EMPTY); + helper.assertTrue(restored.getOrDefault(CNDataComponents.HEAT, -1f) == 0f, + "heat=0 should round-trip through save/parse, got " + + restored.getOrDefault(CNDataComponents.HEAT, -1f)); + helper.succeed(); + } + + // ================================================================ + // 0b. a blueprint with empty pattern slots must survive saving + // ================================================================ + + /** + * Regression test for a second world-save crash, same family as + * {@link #heatComponent_atZero_survivesSerialization} but on the pattern rather than the heat. + *

+ * {@code PatternData.CODEC} used {@link ItemStack#CODEC}, which rejects the empty stack + * ("Item must not be minecraft:air" / "Value must be within range [1;99]: 0"). A reactor + * pattern is 57 slots and is almost never full, so any blueprint sitting in a controller made + * {@code ReactorControllerBlockEntity.write} throw at chunk-save time. The block entity then + * silently stopped persisting — the controller lost its blueprint on every world reload. + *

+ * The fix is {@link ItemStack#OPTIONAL_CODEC}, which encodes the empty stack as {@code {}} + * and leaves the encoding of non-empty stacks untouched, so blueprints already on disk still + * load. + */ + @GameTest(template = STRUCTURE) + public static void blueprintWithEmptyPatternSlots_survivesSerialization(GameTestHelper helper) { + ItemStack blueprint = buildBlueprint(Map.of(18, CNItems.THORIUM_ROD.get())); + + var registries = helper.getLevel().registryAccess(); + Tag saved; + try { + saved = blueprint.save(registries); + } catch (RuntimeException e) { + throw new GameTestAssertException( + "a blueprint whose pattern has empty slots must be serializable, got: " + e.getMessage()); + } + + ItemStack restored = ItemStack.parse(registries, saved).orElse(ItemStack.EMPTY); + ReactorBluePrintData data = restored.get(CNDataComponents.REACTOR_BLUE_PRINT_DATA); + helper.assertTrue(data != null, "the pattern component should round-trip through save/parse"); + + helper.assertTrue(data.pattern().length == PATTERN_SLOTS, + "all " + PATTERN_SLOTS + " pattern slots should round-trip, got " + data.pattern().length); + helper.assertTrue(data.pattern()[18].stack().is(CNItems.THORIUM_ROD.get()), + "the populated slot should keep its rod, got " + data.pattern()[18].stack()); + helper.assertTrue(data.pattern()[0].stack().isEmpty(), + "an empty slot should round-trip as empty, got " + data.pattern()[0].stack()); + helper.succeed(); + } + + // ================================================================ + // 0c. the same blueprint must survive being synced to a client + // ================================================================ + + /** + * Same defect as {@link #blueprintWithEmptyPatternSlots_survivesSerialization}, on the network + * path: {@code PatternData.STREAM_CODEC} used {@link ItemStack#STREAM_CODEC}, which throws + * {@code EncoderException("Empty ItemStack not allowed")} on the empty stack. Since + * {@code REACTOR_BLUE_PRINT_DATA} is registered as {@code networkSynchronized}, merely holding + * a blueprint would fail to encode when the stack was sent to a client. + */ + @GameTest(template = STRUCTURE) + public static void blueprintWithEmptyPatternSlots_survivesNetworkSync(GameTestHelper helper) { + ItemStack blueprint = buildBlueprint(Map.of(18, CNItems.THORIUM_ROD.get())); + + RegistryFriendlyByteBuf buf = + new RegistryFriendlyByteBuf(Unpooled.buffer(), helper.getLevel().registryAccess()); + try { + ItemStack.STREAM_CODEC.encode(buf, blueprint); + } catch (RuntimeException e) { + throw new GameTestAssertException( + "a blueprint whose pattern has empty slots must be network-encodable, got: " + e.getMessage()); + } + + ItemStack restored = ItemStack.STREAM_CODEC.decode(buf); + ReactorBluePrintData data = restored.get(CNDataComponents.REACTOR_BLUE_PRINT_DATA); + helper.assertTrue(data != null, "the pattern component should round-trip over the network"); + helper.assertTrue(data.pattern()[18].stack().is(CNItems.THORIUM_ROD.get()), + "the populated slot should keep its rod, got " + data.pattern()[18].stack()); + helper.assertTrue(data.pattern()[0].stack().isEmpty(), + "an empty slot should round-trip as empty, got " + data.pattern()[0].stack()); + helper.succeed(); + } + + // ================================================================ + // 1. single fuel rod, no neighbors + // ================================================================ + + @GameTest(template = STRUCTURE) + public static void singleFuelRod_noNeighbors_addsOnlyItsOwnBaseRodHeat(GameTestHelper helper) { + Item thorium = CNItems.THORIUM_ROD.get(); + int baseRodHeat = CNConfigs.server().rods.baseValueThorium.get(); + + ReactorControllerInventory inventory = placeController(helper, new BlockPos(1, 1, 1)); + // slot 18: middle row, no adjacent slot populated -> no neighbor bonus possible + loadPattern(inventory, Map.of(18, thorium)); + + ReactorDisplayState displayState = new ReactorDisplayState(Map.of(thorium, 1), List.of(), 0); + double overHeat = 10.0; + + double heat = CALCULATOR.computeHeat(null, null, inventory, overHeat, displayState, helper.getLevel()); + + helper.assertTrue(Math.abs(heat - (baseRodHeat + overHeat)) < DELTA, + "an isolated fuel rod should only contribute its own baseRodHeat, plus overHeat: expected " + + (baseRodHeat + overHeat) + ", got " + heat); + helper.succeed(); + } + + // ================================================================ + // 2. single cooler rod, no neighbors + // ================================================================ + + @GameTest(template = STRUCTURE) + public static void singleCoolerRod_noNeighbors_addsOnlyItsOwnBaseRodHeat(GameTestHelper helper) { + Item graphite = CNItems.GRAPHITE_ROD.get(); + int baseRodHeat = CNConfigs.server().rods.graphiteBaseValue.get(); + + ReactorControllerInventory inventory = placeController(helper, new BlockPos(1, 1, 1)); + loadPattern(inventory, Map.of(18, graphite)); + + ReactorDisplayState displayState = new ReactorDisplayState(Map.of(graphite, 1), List.of(), 0); + + // computeHeat clamps its result to a minimum of 0 (Math.max(0, heat+overHeat)); an isolated + // cooler's own baseRodHeat is negative by default, so a large overHeat is added here to keep + // the total positive and actually observe baseRodHeat's contribution instead of it being + // swallowed by the floor. + double overHeat = 50.0; + + double heat = CALCULATOR.computeHeat(null, null, inventory, overHeat, displayState, helper.getLevel()); + + helper.assertTrue(Math.abs(heat - (baseRodHeat + overHeat)) < DELTA, + "a cooler contributes its own baseRodHeat exactly like a fuel rod would, when isolated: expected " + + (baseRodHeat + overHeat) + ", got " + heat); + helper.succeed(); + } + + // ================================================================ + // 3. fuel/cooler mix adjacency: cooler scans its own fuel neighbors symmetrically + // to a fuel rod, matching the wiki calculator / external spec + // ("Graphite extra: -1/4Q of the heating rod") + // ================================================================ + + /** + * Layout (row 3 of {@code FORMATTED_PATTERN}, three consecutive slots): + * uranium A (18) - thorium B (19) - graphite C (20). + *

+ * Expected total = sum of each rod's own baseRodHeat, PLUS proximity contributions from + * both fuel-fuel and cooler-fuel adjacency (cooler-cooler and fuel-cooler-from-the-fuel-side + * contribute nothing): + *

    + *
  • A's scan (fuel, neighbor B is fuel) -> + A.proximityRodHeat()
  • + *
  • B's scan (fuel, neighbor A is fuel) -> + B.proximityRodHeat()
  • + *
  • B's scan (fuel, neighbor C is cooler) -> contributes nothing (fuel only scores against fuel neighbors)
  • + *
  • C's scan (cooler, neighbor B is fuel) -> + B.baseRodHeat() * C.proximityRodHeat()
  • + *
+ */ + @GameTest(template = STRUCTURE) + public static void fuelCoolerMix_coolerScansItsOwnFuelNeighborsSymmetrically(GameTestHelper helper) { + Item uranium = CNItems.URANIUM_ROD.get(); + Item thorium = CNItems.THORIUM_ROD.get(); + Item graphite = CNItems.GRAPHITE_ROD.get(); + + int uraniumBase = CNConfigs.server().rods.uraniumBaseValue.get(); + float uraniumProxy = CNConfigs.server().rods.uraniumProximityBonus.get(); + int thoriumBase = CNConfigs.server().rods.baseValueThorium.get(); + float thoriumProxy = CNConfigs.server().rods.thoriumProxyBonus.get(); + int graphiteBase = CNConfigs.server().rods.graphiteBaseValue.get(); + float graphiteProxy = CNConfigs.server().rods.graphiteProximityMalus.getF(); + + ReactorControllerInventory inventory = placeController(helper, new BlockPos(1, 1, 1)); + loadPattern(inventory, Map.of(18, uranium, 19, thorium, 20, graphite)); + + ReactorDisplayState displayState = new ReactorDisplayState( + Map.of(uranium, 1, thorium, 1, graphite, 1), List.of(), 0); + + double heat = CALCULATOR.computeHeat(null, null, inventory, /*overHeat*/ 0.0, displayState, helper.getLevel()); + + double expected = (uraniumBase + thoriumBase + graphiteBase) // each rod's own baseRodHeat + + uraniumProxy // A's scan: fuel neighbor B (thorium) -> addition + + thoriumProxy // B's scan: fuel neighbor A (uranium) -> addition + + (thoriumBase * graphiteProxy); + // C's scan: fuel neighbor B (thorium) -> multiplication (neighbor's base * cooler's own proximity) + // B's scan towards C contributes 0: fuel only scores against fuel neighbors + + helper.assertTrue(Math.abs(heat - expected) < DELTA, + "cooler must score its own malus against its fuel neighbor: expected " + + expected + ", got " + heat); + helper.succeed(); + } + + // ================================================================ + // 4. 3x3 diamond of rods: cross-checked against the community wiki calculator + // ================================================================ + + /** + * Layout (rows 3-5, columns 3-5 of {@code FORMATTED_PATTERN} — a fully interior 3x3 block, + * every position outside it stays empty so neighbor counts match an isolated 3x3 grid): + *
+     * graphite(18) thorium(19) graphite(20)
+     * thorium(27)  uranium(28) thorium(29)
+     * graphite(36) thorium(37) graphite(38)
+     * 
+ * With the mod's default balance values this totals {@code 128}, matching the value produced + * by the community wiki calculator for the same pattern — but the assertion below is derived + * from the live config, not hardcoded, so it stays correct if the default balance changes: + *
    + *
  • 4 corner graphites, each with 2 thorium neighbors -> + * {@code graphiteBase + 2 * (thoriumBase * graphiteProxy)} each
  • + *
  • 4 edge thoriums, each with 2 graphite neighbors (ignored, cooler) + 1 uranium neighbor (fuel) -> + * {@code thoriumBase + thoriumProxy} each
  • + *
  • 1 center uranium, with 4 thorium neighbors (all fuel) -> + * {@code uraniumBase + 4 * uraniumProxy}
  • + *
+ */ + @GameTest(template = STRUCTURE) + public static void threeByThreeDiamond_matchesWikiCalculatorReferenceValue(GameTestHelper helper) { + Item uranium = CNItems.URANIUM_ROD.get(); + Item thorium = CNItems.THORIUM_ROD.get(); + Item graphite = CNItems.GRAPHITE_ROD.get(); + + int uraniumBase = CNConfigs.server().rods.uraniumBaseValue.get(); + float uraniumProxy = CNConfigs.server().rods.uraniumProximityBonus.get(); + int thoriumBase = CNConfigs.server().rods.baseValueThorium.get(); + float thoriumProxy = CNConfigs.server().rods.thoriumProxyBonus.get(); + int graphiteBase = CNConfigs.server().rods.graphiteBaseValue.get(); + float graphiteProxy = CNConfigs.server().rods.graphiteProximityMalus.getF(); + + ReactorControllerInventory inventory = placeController(helper, new BlockPos(1, 1, 1)); + loadPattern(inventory, Map.ofEntries( + Map.entry(18, graphite), Map.entry(19, thorium), Map.entry(20, graphite), + Map.entry(27, thorium), Map.entry(28, uranium), Map.entry(29, thorium), + Map.entry(36, graphite), Map.entry(37, thorium), Map.entry(38, graphite) + )); + + ReactorDisplayState displayState = new ReactorDisplayState( + Map.of(uranium, 1, thorium, 4, graphite, 4), List.of(), 0); + + double heat = CALCULATOR.computeHeat(null, null, inventory, /*overHeat*/ 0.0, displayState, helper.getLevel()); + + double cornerGraphite = graphiteBase + 2 * (thoriumBase * graphiteProxy); + double edgeThorium = thoriumBase + thoriumProxy; + double centerUranium = uraniumBase + 4 * uraniumProxy; + double expected = 4 * cornerGraphite + 4 * edgeThorium + centerUranium; + + helper.assertTrue(Math.abs(heat - expected) < DELTA, + "3x3 diamond should match the wiki calculator's reference value for this pattern: expected " + + expected + " (128 with default balance), got " + heat); + helper.succeed(); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/gametest/ReactorInputFluidManagerGameTest.java b/src/main/java/net/nuclearteam/createnuclear/gametest/ReactorInputFluidManagerGameTest.java new file mode 100644 index 0000000..2ae58d0 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/gametest/ReactorInputFluidManagerGameTest.java @@ -0,0 +1,455 @@ +package net.nuclearteam.createnuclear.gametest; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.Fluids; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.fluids.capability.IFluidHandler.FluidAction; +import net.neoforged.neoforge.gametest.GameTestHolder; +import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputFluidManager; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.ReactorFluidInputEntity; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.VirtualReactorInputFluid; +import net.nuclearteam.createnuclear.foundation.block.MultiDirectionalReactorBlock; + +import java.util.List; + +/** + * GameTest coverage for {@link ReactorInputFluidManager}, run against a real + * {@code ServerLevel} and real {@link ReactorFluidInputEntity} blocks (no mocks). + *

+ * All tests share the "empty_platform" structure + * (data/createnuclear/structure/empty_platform.nbt): a 5x3x5 area with a + * stone floor at y=0, leaving y=1..2 free to place fluid input blocks. The structure + * is a real compressed structure-block export (a hand-authored .snbt cannot be loaded + * directly here). Note the folder is {@code structure}, singular: 1.21 renamed the + * data folders that Forge 1.20.1 spelled {@code structures}. + *

+ * Capability access goes through {@code level.getCapability(Capabilities.FluidHandler.BLOCK, ...)} + * instead of Forge's {@code be.getCapability(ForgeCapabilities.FLUID_HANDLER)}, and fluid ids are + * resolved via {@code BuiltInRegistries.FLUID} instead of {@code ForgeRegistries.FLUIDS}. + *

+ * Tests named "*_expectedContract" cover the two extractFluids defects fixed on both branches: + * fluidNeeded was never decremented between handlers (so a request of 10 units drained 10 from + * EVERY input), and a request for exactly one unit was silently dropped by an + * {@code if (toExtract > 1)} guard. The whole suite passes; the two characterization tests that + * pinned the buggy behaviour were removed with the fix. + */ +@GameTestHolder(CreateNuclear.MOD_ID) +@PrefixGameTestTemplate(false) +public class ReactorInputFluidManagerGameTest { + + private static final String STRUCTURE = "empty_platform"; + + // ---------- test fixtures ---------- + + private static void place(GameTestHelper helper, BlockPos rel, Direction facing) { + helper.setBlock(rel, CNBlocks.REACTOR_FLUID_INPUT.get().defaultBlockState() + .setValue(MultiDirectionalReactorBlock.FACING, facing)); + } + + private static IFluidHandler handler(GameTestHelper helper, BlockPos rel) { + return helper.getLevel().getCapability(Capabilities.FluidHandler.BLOCK, helper.absolutePos(rel), null); + } + + private static void fill(GameTestHelper helper, BlockPos rel, FluidStack stack) { + IFluidHandler h = handler(helper, rel); + if (h != null) h.fill(stack, FluidAction.EXECUTE); + } + + private static int tankAmount(GameTestHelper helper, BlockPos rel) { + IFluidHandler h = handler(helper, rel); + return h == null ? -1 : h.getFluidInTank(0).getAmount(); + } + + private static ReactorInputFluidManager manager(GameTestHelper helper, BlockPos... relPositions) { + ReactorInputFluidManager manager = new ReactorInputFluidManager(); + for (BlockPos rel : relPositions) manager.addBlock(helper.absolutePos(rel)); + return manager; + } + + // ================================================================ + // read / write (pure NBT, no world interaction required) + // ================================================================ + + @GameTest(template = STRUCTURE) + public static void read_absentKey_leavesEmpty(GameTestHelper helper) { + ReactorInputFluidManager manager = new ReactorInputFluidManager(); + manager.read(new CompoundTag()); + + helper.assertTrue(manager.size() == 0, "expected no tracked positions when NBT key is absent"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void read_clearsPreviousPositions(GameTestHelper helper) { + ReactorInputFluidManager manager = new ReactorInputFluidManager(); + manager.addBlock(new BlockPos(1, 2, 3)); + + manager.read(new CompoundTag()); + + helper.assertTrue(manager.size() == 0, "read() must clear previously tracked positions before loading"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void read_singleEntry_roundTrips(GameTestHelper helper) { + CompoundTag entry = new CompoundTag(); + entry.putInt("x", 5); + entry.putInt("y", 64); + entry.putInt("z", -3); + ListTag list = new ListTag(); + list.add(entry); + CompoundTag root = new CompoundTag(); + root.put("ReactorInputFluid", list); + + ReactorInputFluidManager manager = new ReactorInputFluidManager(); + manager.read(root); + + helper.assertTrue(manager.size() == 1, "expected exactly one entry after read"); + helper.assertTrue(manager.contains(new BlockPos(5, 64, -3)), "expected BlockPos(5,64,-3) to be present"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void read_multipleEntries_preservesOrder(GameTestHelper helper) { + BlockPos a = new BlockPos(0, 0, 0); + BlockPos b = new BlockPos(1, 1, 1); + BlockPos c = new BlockPos(2, 2, 2); + + ListTag list = new ListTag(); + for (BlockPos p : List.of(a, b, c)) { + CompoundTag entry = new CompoundTag(); + entry.putInt("x", p.getX()); + entry.putInt("y", p.getY()); + entry.putInt("z", p.getZ()); + list.add(entry); + } + CompoundTag root = new CompoundTag(); + root.put("ReactorInputFluid", list); + + ReactorInputFluidManager manager = new ReactorInputFluidManager(); + manager.read(root); + + helper.assertTrue(manager.getBlocksPosition().equals(List.of(a, b, c)), + "expected insertion order to be preserved, found " + manager.getBlocksPosition()); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void write_emptyPositions_stillWritesKey(GameTestHelper helper) { + CompoundTag tag = new CompoundTag(); + new ReactorInputFluidManager().write(tag); + + helper.assertTrue(tag.contains("ReactorInputFluid"), "write() should always write the NBT key, even when empty"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void write_then_read_roundTrip(GameTestHelper helper) { + BlockPos a = new BlockPos(1, 2, 3); + BlockPos b = new BlockPos(-5, 64, 100); + + ReactorInputFluidManager original = new ReactorInputFluidManager(); + original.addBlock(a); + original.addBlock(b); + + CompoundTag tag = new CompoundTag(); + original.write(tag); + + ReactorInputFluidManager restored = new ReactorInputFluidManager(); + restored.read(tag); + + helper.assertTrue(restored.getBlocksPosition().equals(List.of(a, b)), + "round-trip through NBT should preserve exact positions and order"); + helper.succeed(); + } + + // ================================================================ + // clearInvalid + // ================================================================ + + @GameTest(template = STRUCTURE) + public static void clearInvalid_missingBlockEntity_removesPosition(GameTestHelper helper) { + BlockPos rel = new BlockPos(1, 1, 1); // never placed: air, no block entity + ReactorInputFluidManager manager = manager(helper, rel); + + manager.clearInvalid(helper.getLevel()); + + helper.assertTrue(manager.size() == 0, "a position without a block entity should be removed"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void clearInvalid_noCapability_removesPosition(GameTestHelper helper) { + BlockPos rel = new BlockPos(1, 1, 1); + helper.setBlock(rel, Blocks.CHEST.defaultBlockState()); // real BE, no fluid capability + ReactorInputFluidManager manager = manager(helper, rel); + + manager.clearInvalid(helper.getLevel()); + + helper.assertTrue(manager.size() == 0, "a block entity without a fluid capability should be removed"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void clearInvalid_validCapability_keepsPosition(GameTestHelper helper) { + BlockPos rel = new BlockPos(1, 1, 1); + place(helper, rel, Direction.NORTH); + ReactorInputFluidManager manager = manager(helper, rel); + + manager.clearInvalid(helper.getLevel()); + + helper.assertTrue(manager.size() == 1, "a valid ReactorFluidInputEntity should be kept"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void clearInvalid_mixedSet_onlyInvalidRemoved(GameTestHelper helper) { + BlockPos valid = new BlockPos(1, 1, 1); + BlockPos chest = new BlockPos(3, 1, 1); + BlockPos missing = new BlockPos(1, 1, 3); + + place(helper, valid, Direction.NORTH); + helper.setBlock(chest, Blocks.CHEST.defaultBlockState()); + + ReactorInputFluidManager manager = manager(helper, valid, chest, missing); + manager.clearInvalid(helper.getLevel()); + + helper.assertTrue(manager.getBlocksPosition().equals(List.of(helper.absolutePos(valid))), + "only the valid fluid input position should remain, found " + manager.getBlocksPosition()); + helper.succeed(); + } + + // ================================================================ + // getBlocksPosition(Level) + // ================================================================ + + @GameTest(template = STRUCTURE) + public static void getBlocksPosition_filtersNonMatchingEntityType(GameTestHelper helper) { + BlockPos validRel = new BlockPos(1, 1, 1); + BlockPos otherRel = new BlockPos(3, 1, 1); + place(helper, validRel, Direction.NORTH); + helper.setBlock(otherRel, Blocks.CHEST.defaultBlockState()); + + ReactorInputFluidManager manager = manager(helper, validRel, otherRel); + + List result = manager.getBlocksPosition(helper.getLevel()); + + helper.assertTrue(result.equals(List.of(helper.absolutePos(validRel))), + "only the ReactorFluidInputEntity position should be returned, found " + result); + helper.succeed(); + } + + // ================================================================ + // getFuildHandlers + // ================================================================ + + @GameTest(template = STRUCTURE) + public static void getFuildHandlers_capabilityPresent_included(GameTestHelper helper) { + BlockPos rel = new BlockPos(1, 1, 1); + place(helper, rel, Direction.NORTH); + fill(helper, rel, new FluidStack(Fluids.WATER, 500)); + + List handlers = manager(helper, rel).getFuildHandlers(helper.getLevel()); + + helper.assertTrue(handlers.size() == 1, "expected exactly one handler"); + helper.assertTrue(handlers.get(0).getFluidInTank(0).getAmount() == 500, + "handler should expose the filled tank content"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void getFuildHandlers_preservesTrackingOrder(GameTestHelper helper) { + BlockPos rel1 = new BlockPos(1, 1, 1); + BlockPos rel2 = new BlockPos(3, 1, 1); + place(helper, rel1, Direction.NORTH); + place(helper, rel2, Direction.NORTH); + fill(helper, rel1, new FluidStack(Fluids.WATER, 100)); + fill(helper, rel2, new FluidStack(Fluids.LAVA, 200)); + + List handlers = manager(helper, rel1, rel2).getFuildHandlers(helper.getLevel()); + + helper.assertTrue(handlers.size() == 2, "expected two handlers"); + helper.assertTrue(handlers.get(0).getFluidInTank(0).getFluid() == Fluids.WATER, + "first handler should be the water tank (matches insertion order)"); + helper.assertTrue(handlers.get(1).getFluidInTank(0).getFluid() == Fluids.LAVA, + "second handler should be the lava tank (matches insertion order)"); + helper.succeed(); + } + + // ================================================================ + // getInventory + // ================================================================ + + @GameTest(template = STRUCTURE) + public static void getInventory_noHandlers_returnsEmpty(GameTestHelper helper) { + VirtualReactorInputFluid inventory = new ReactorInputFluidManager().getInventory(helper.getLevel()); + + helper.assertTrue(inventory.fluids().isEmpty(), "expected an empty inventory with no tracked handlers"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void getInventory_aggregatesAcrossHandlers(GameTestHelper helper) { + BlockPos rel1 = new BlockPos(1, 1, 1); + BlockPos rel2 = new BlockPos(3, 1, 1); + place(helper, rel1, Direction.NORTH); + place(helper, rel2, Direction.NORTH); + fill(helper, rel1, new FluidStack(Fluids.WATER, 300)); + fill(helper, rel2, new FluidStack(Fluids.WATER, 250)); + + VirtualReactorInputFluid inventory = manager(helper, rel1, rel2).getInventory(helper.getLevel()); + + ResourceLocation waterId = BuiltInRegistries.FLUID.getKey(Fluids.WATER); + long total = inventory.getAmount(waterId); + helper.assertTrue(total == 550, "expected aggregated total of 550, found " + total); + helper.succeed(); + } + + // ================================================================ + // extractFluids — core of the audited bug + // ================================================================ + + @GameTest(template = STRUCTURE) + public static void extractFluids_nullLevel_returnsFalse(GameTestHelper helper) { + boolean result = new ReactorInputFluidManager().extractFluids(null, 10); + helper.assertTrue(!result, "extractFluids should return false for a null level"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void extractFluids_noHandlers_returnsFalse(GameTestHelper helper) { + boolean result = new ReactorInputFluidManager().extractFluids(helper.getLevel(), 10); + helper.assertTrue(!result, "extractFluids should return false when there are no handlers"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void extractFluids_singleHandlerEnoughStock_drainsExactAmount(GameTestHelper helper) { + BlockPos rel = new BlockPos(1, 1, 1); + place(helper, rel, Direction.NORTH); + fill(helper, rel, new FluidStack(Fluids.WATER, 1000)); + + boolean result = manager(helper, rel).extractFluids(helper.getLevel(), 400); + + helper.assertTrue(result, "extraction should succeed when enough fluid is available"); + helper.assertTrue(tankAmount(helper, rel) == 600, "expected 600 remaining, found " + tankAmount(helper, rel)); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void extractFluids_singleHandlerInsufficientStock_drainsAvailable(GameTestHelper helper) { + BlockPos rel = new BlockPos(1, 1, 1); + place(helper, rel, Direction.NORTH); + fill(helper, rel, new FluidStack(Fluids.WATER, 30)); + + boolean result = manager(helper, rel).extractFluids(helper.getLevel(), 100); + + helper.assertTrue(result, "extraction should be reported successful even for a partial drain"); + helper.assertTrue(tankAmount(helper, rel) == 0, "all 30 available units should have been drained"); + helper.succeed(); + } + + /** + * A request for exactly 1 unit with stock available must succeed. This used to fail against + * an {@code if (toExtract > 1)} guard that silently dropped single-unit requests. + */ + @GameTest(template = STRUCTURE) + public static void extractFluids_needOfOne_shouldSucceed_expectedContract(GameTestHelper helper) { + BlockPos rel = new BlockPos(1, 1, 1); + place(helper, rel, Direction.NORTH); + fill(helper, rel, new FluidStack(Fluids.WATER, 5)); + + boolean result = manager(helper, rel).extractFluids(helper.getLevel(), 1); + + helper.assertTrue(result, "a request for exactly 1 unit with stock available should succeed"); + helper.assertTrue(tankAmount(helper, rel) == 4, "expected exactly 1 unit to be drained"); + helper.succeed(); + } + + /** + * Extracting 10 units from a 20-unit pool spread across two handlers must leave 10 total + * remaining. The requested amount is a total across every input, not a per-input quota; + * this used to drain both handlers in full because {@code fluidNeeded} was never + * decremented between them. + */ + @GameTest(template = STRUCTURE) + public static void extractFluids_twoHandlers_shouldNotOverExtract_expectedContract(GameTestHelper helper) { + BlockPos rel1 = new BlockPos(1, 1, 1); + BlockPos rel2 = new BlockPos(3, 1, 1); + place(helper, rel1, Direction.NORTH); + place(helper, rel2, Direction.NORTH); + fill(helper, rel1, new FluidStack(Fluids.WATER, 10)); + fill(helper, rel2, new FluidStack(Fluids.WATER, 10)); + + manager(helper, rel1, rel2).extractFluids(helper.getLevel(), 10); + + int totalRemaining = tankAmount(helper, rel1) + tankAmount(helper, rel2); + helper.assertTrue(totalRemaining == 10, + "extracting 10 out of a 20-unit pool should leave 10 total remaining, found " + totalRemaining); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void extractFluids_needZero_leavesTanksUntouched(GameTestHelper helper) { + BlockPos rel1 = new BlockPos(1, 1, 1); + BlockPos rel2 = new BlockPos(3, 1, 1); + place(helper, rel1, Direction.NORTH); + place(helper, rel2, Direction.NORTH); + fill(helper, rel1, new FluidStack(Fluids.WATER, 10)); + fill(helper, rel2, new FluidStack(Fluids.WATER, 10)); + + boolean result = manager(helper, rel1, rel2).extractFluids(helper.getLevel(), 0); + + helper.assertTrue(!result, "a non-positive fluidNeeded should never extract anything"); + helper.assertTrue(tankAmount(helper, rel1) == 10 && tankAmount(helper, rel2) == 10, + "no tank should be touched when fluidNeeded <= 0"); + helper.succeed(); + } + + @GameTest(template = STRUCTURE) + public static void extractFluids_emptyStackHandler_skippedGracefully(GameTestHelper helper) { + BlockPos rel1 = new BlockPos(1, 1, 1); + BlockPos rel2 = new BlockPos(3, 1, 1); + place(helper, rel1, Direction.NORTH); // left empty + place(helper, rel2, Direction.NORTH); + fill(helper, rel2, new FluidStack(Fluids.WATER, 20)); + + boolean result = manager(helper, rel1, rel2).extractFluids(helper.getLevel(), 15); + + helper.assertTrue(result, "the second, non-empty handler should still be usable"); + helper.assertTrue(tankAmount(helper, rel1) == 0, "empty handler should stay untouched"); + helper.assertTrue(tankAmount(helper, rel2) == 5, "expected 15 drained out of 20, 5 remaining"); + helper.succeed(); + } + + /** + * A partial extraction still reports success: the reactor consumes whatever coolant it can + * reach rather than refusing to run. The Javadoc used to promise "true if the full amount + * was extracted", which never matched the implementation; it now documents this contract. + */ + @GameTest(template = STRUCTURE) + public static void extractFluids_partialExtraction_stillReportsSuccess(GameTestHelper helper) { + BlockPos rel = new BlockPos(1, 1, 1); + place(helper, rel, Direction.NORTH); + fill(helper, rel, new FluidStack(Fluids.WATER, 30)); + + boolean result = manager(helper, rel).extractFluids(helper.getLevel(), 100); + + helper.assertTrue(result, "a partial extraction should still report success"); + helper.assertTrue(tankAmount(helper, rel) == 0, "all available fluid should have been drained"); + helper.succeed(); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/impl/registry/CreateNuclearRegistriesImpl.java b/src/main/java/net/nuclearteam/createnuclear/impl/registry/CreateNuclearRegistriesImpl.java new file mode 100644 index 0000000..5c5d6dd --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/impl/registry/CreateNuclearRegistriesImpl.java @@ -0,0 +1,36 @@ +package net.nuclearteam.createnuclear.impl.registry; + +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.registries.DataPackRegistryEvent; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.CreateNuclearRegistries; +import net.nuclearteam.createnuclear.api.multiblock.fluid.ReactorFluidType; +import net.nuclearteam.createnuclear.api.multiblock.rods.RodType; +import org.jetbrains.annotations.ApiStatus.Internal; + +/** + * Declares the mod's custom datapack registries. Without this, the registries have no codec + * registered, so datagen cannot clone them ("No cloner for createnuclear:fluids/type") and they + * would never be loaded from datapacks at runtime. + */ +@EventBusSubscriber(modid = CreateNuclear.MOD_ID) +public class CreateNuclearRegistriesImpl { + private CreateNuclearRegistriesImpl() {} + + @Internal + @SubscribeEvent + public static void registerDatapackRegistries(DataPackRegistryEvent.NewRegistry event) { + event.dataPackRegistry( + CreateNuclearRegistries.ROD_TYPE, + RodType.CODEC, + RodType.CODEC + ); + + event.dataPackRegistry( + CreateNuclearRegistries.FLUID_TYPE, + ReactorFluidType.CODEC, + ReactorFluidType.CODEC + ); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CBiomeRestore.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CBiomeRestore.java new file mode 100644 index 0000000..a91c2bb --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CBiomeRestore.java @@ -0,0 +1,23 @@ +package net.nuclearteam.createnuclear.infrastructure.config; + +import net.createmod.catnip.config.ConfigBase; +import net.minecraft.MethodsReturnNonnullByDefault; +import net.nuclearteam.createnuclear.CNParticleTypes; + +@MethodsReturnNonnullByDefault +public class CBiomeRestore extends ConfigBase { + public final ConfigBool restoreInCircle = b(true, "restore_in_circle", Comments.restoreInCircle); + public final ConfigInt restoreRadiusChunks = i(4, 0, 32, "restore_radius_chunks", Comments.restoreRadiusChunks); + public final ConfigInt maxCharge = i(8, 1, 64, "maxCharge", Comments.maxCharge); + + @Override + public String getName() { + return "biomeRestore"; + } + + private static class Comments { + static String maxCharge = "Maximum number of charges the Biome Restore Cell can hold."; + static String restoreInCircle = "When enabled, restoring an irradiated biome also restores the surrounding chunks within restore_radius_chunks. When disabled, only the chunk being targeted is restored."; + static String restoreRadiusChunks = "Radius, in chunks, of the circular area restored around the targeted chunk. Only used when restore_in_circle is enabled."; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CExplode.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CExplode.java new file mode 100644 index 0000000..279a7c1 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CExplode.java @@ -0,0 +1,20 @@ +package net.nuclearteam.createnuclear.infrastructure.config; + +import net.createmod.catnip.config.ConfigBase; + +public class CExplode extends ConfigBase { + public final ConfigInt size = i(10, "Size of the reactor explosion"); + public final ConfigInt type = i(1, 0, 2, "Type of explosion", Comments.type); + public final ConfigInt time = i(600, 100, 1200, "Duration before exploration", Comments.explosionTime, Comments.hintExplosion); + + @Override + public String getName() { + return "Explosion Reactor"; + } + + private static class Comments { + static String explosionTime = "Create Nuclear Explosion Time"; + static String hintExplosion = "300 ticks = 15 seconds"; + static String type = "Explanation: 0 = no explosion, 1 = current explosion, 2 = new explosion."; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CExplose.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CExplose.java deleted file mode 100644 index 1f27167..0000000 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CExplose.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.nuclearteam.createnuclear.infrastructure.config; - -import net.createmod.catnip.config.ConfigBase; - -public class CExplose extends ConfigBase { - public final ConfigInt size = i(10, "Size of the reactor explosion"); - public final ConfigInt type = i(1, 0, 2, "Type of explosion", Comments.type); - public final ConfigInt time = i(600, 100, 1200, "Duration before exploration", Comments.explosionTime, Comments.hintExplosion); - - @Override - public String getName() { - return "Explosion Reactor"; - } - - private static class Comments { - static String explosionTime = "Create Nuclear Explosion Time"; - static String hintExplosion = "300 ticks = 15 seconds"; - static String type = "Explanation: 0 = no explosion, 1 = current explosion, 2 = new explosion."; - } -} diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCClient.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCClient.java index 0bbd899..77a2837 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCClient.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCClient.java @@ -1,4 +1,16 @@ package net.nuclearteam.createnuclear.infrastructure.config; -public class CNCClient { +import net.createmod.catnip.config.ConfigBase; + +public class CNCClient extends ConfigBase { + public final ConfigBool nuclearBombFlash = b(true, "nuclear_bomb_flash", Comments.nuclearBombFlash); + public final ConfigBool screenShaking = b(true, "screen_shake", Comments.screenShaking); + + @Override + public String getName() { return "client"; } + + private static class Comments { + static String nuclearBombFlash = "Enable the bright flash at the start of a nuclear explosion."; + static String screenShaking = "Enable screen shake effect during a nuclear explosion."; + } } diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCCommon.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCCommon.java index cf642f7..9d85f11 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCCommon.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCCommon.java @@ -4,8 +4,6 @@ public class CNCCommon extends ConfigBase { public final CWorldGen worldGen = nested(0, CWorldGen::new, Comments.worldGen); - public final CRods rods = nested(0, CRods::new, Comments.rods); - public final CExplose explode = nested(0, CExplose::new, Comments.explode); @Override public String getName() { @@ -13,8 +11,6 @@ public String getName() { } private static class Comments { - static String worldGen = "Modify CreateNuclear's impact on your terrain"; - static String rods = "Modify rods time and config"; - static String explode = "Explose: pas d'idée"; + static String worldGen = "Modify how CreateNuclear affects world generation."; } } diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCServer.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCServer.java index 6192b4d..ac41f5d 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCServer.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNCServer.java @@ -1,4 +1,24 @@ package net.nuclearteam.createnuclear.infrastructure.config; -public class CNCServer { -} +import net.createmod.catnip.config.ConfigBase; + +public class CNCServer extends ConfigBase { + public final CRods rods = nested(0, CRods::new, Comments.rods); + public final CNotify notify = nested(0, CNotify::new, Comments.notify); + public final CRadiation radiation = nested(0, CRadiation::new, Comments.radiation); + public final CReactorHeat reactorHeat = nested(0, CReactorHeat::new, Comments.reactorHeat); + public final CBiomeRestore biomeRestore = nested(0, CBiomeRestore::new, Comments.biomeRestore); + + @Override + public String getName() { + return "Server"; + } + + private static class Comments { + static String rods = "Modify rod durations and related parameters."; + static String radiation = "Enable or disable radiation effects emitted by mod items. "; + static String notify = "Notification settings for reactor warnings."; + static String reactorHeat = "Heat thresholds for different reactor sizes"; + static String biomeRestore = "Control how irradiated biomes are restored back to their original biome."; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNConfigs.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNConfigs.java index 3b2518f..fd1ddc5 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNConfigs.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNConfigs.java @@ -15,18 +15,26 @@ import java.util.Map.Entry; import java.util.function.Supplier; -@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) +@EventBusSubscriber public class CNConfigs { private static final Map CONFIGS = new EnumMap<>(ModConfig.Type.class); private static CNCClient client; private static CNCCommon common; - private static CNCServer server; + public static CNCServer server; + + public static CNCClient client() { + return client; + } public static CNCCommon common() { return common; } + public static CNCServer server() { + return server; + } + public static ConfigBase byType(ModConfig.Type type) { return CONFIGS.get(type); } @@ -45,7 +53,9 @@ private static T register(Supplier factory, ModConfig. } public static void register(ModLoadingContext context, ModContainer container) { + client = register(CNCClient::new, ModConfig.Type.CLIENT); common = register(CNCCommon::new, ModConfig.Type.COMMON); + server = register(CNCServer::new, ModConfig.Type.SERVER); for (Entry pair : CONFIGS.entrySet()) container.registerConfig(pair.getKey(), pair.getValue().specification); diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNotify.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNotify.java new file mode 100644 index 0000000..7ef0c44 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CNotify.java @@ -0,0 +1,18 @@ +package net.nuclearteam.createnuclear.infrastructure.config; + +import net.createmod.catnip.config.ConfigBase; + +public class CNotify extends ConfigBase { + public final ConfigBool warnAllPlayers = b(false, "warn_all_players", Comments.warning); + public final ConfigInt warningDistance = i(100, 30, 5000, "warning_distance_blocks", Comments.rangeOfWarning); + + @Override + public String getName() { + return "Notify"; + } + + private static class Comments { + static String warning = "When true, broadcast a warning to nearby players before a reactor explosion."; + static String rangeOfWarning = "Distance (in blocks) to search for players to warn about impending explosion."; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CRadiation.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CRadiation.java new file mode 100644 index 0000000..14fc636 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CRadiation.java @@ -0,0 +1,70 @@ +package net.nuclearteam.createnuclear.infrastructure.config; + +import net.createmod.catnip.config.ConfigBase; +import net.minecraft.MethodsReturnNonnullByDefault; +import net.neoforged.neoforge.common.ModConfigSpec; +import net.neoforged.neoforge.common.ModConfigSpec.ConfigValue; +import java.util.List; + +@MethodsReturnNonnullByDefault +public class CRadiation extends ConfigBase { + public final ConfigBool enabledItemRadiation = b(true, "enabled_item_radiation", Comments.enabled); + public final ConfigInt radiationLevel1 = i(10, 0, 50, "radiation_level_1", Comments.radiationLevel1); + public final ConfigInt radiationLevel2 = i(25, 0, 50, "radiation_level_2", Comments.radiationLevel2); + public final ConfigInt radiationLevel3 = i(50, 0, 50, "radiation_level_3", Comments.radiationLevel3); + public final ConfigInt amplifierLevel0 = i(0, 0, 10, "amplifier_level_0", Comments.amplifierLevel0); + public final ConfigInt amplifierLevel1 = i(1, 0, 10, "amplifier_level_1", Comments.amplifierLevel1); + public final ConfigInt amplifierLevel2 = i(2, 0, 10, "amplifier_level_2", Comments.amplifierLevel2); + public final ConfiguredLists configuredLists = nested(0, ConfiguredLists::new, Comments.list); + + @Override + public String getName() { + return "Radiation"; + } + + private static class Comments { + static String enabled = "When enabled, certain items may emit radiation affecting players and nearby entities. Disable to turn off radiation effects without removing items."; + static String radiationLevel1 = "Minimum radiation value required to apply Radiation I. Values below this do not apply effects."; + static String radiationLevel2 = "Minimum radiation value required to apply Radiation II. Should be greater than radiation_level_1."; + static String radiationLevel3 = "Minimum radiation value required to apply Radiation III. Should be greater than radiation_level_2."; + static String amplifierLevel0 = "Effect amplifier for Radiation I (0 = level I)."; + static String amplifierLevel1 = "Effect amplifier for Radiation II (1 = level II)."; + static String amplifierLevel2 = "Effect amplifier for Radiation III (2 = level III)."; + static String list = "Lists related to radiation configuration, for example the entity blacklist."; + static String blackListEntity = + "List of entity IDs excluded from radiation effects. Use registry names like \"minecraft:armor_stand\".\n\n" + + "How to edit:\n" + + "- Add entries as namespace:entity_name strings.\n" + + "- Example: \"minecraft:armor_stand\"\n" + + "- Remove an entry to stop excluding it.\n"; + } + + public static class ConfiguredLists extends ConfigBase { + private static ConfigValue> ENTITY_BLACKLIST = null; + + @Override + public void registerAll(ModConfigSpec.Builder builder) { + + ENTITY_BLACKLIST = builder + .comment(Comments.blackListEntity) + .defineListAllowEmpty( + List.of("entity_blacklist"), + () -> List.of( + "minecraft:armor_stand", + "minecraft:item_frame", + "minecraft:glow_item_frame" + ), + obj -> obj instanceof String + ); + } + + @Override + public String getName() { + return "lists"; + } + + public List getEntityBlackList() { + return ENTITY_BLACKLIST.get(); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CReactorHeat.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CReactorHeat.java new file mode 100644 index 0000000..6d10f36 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CReactorHeat.java @@ -0,0 +1,14 @@ +package net.nuclearteam.createnuclear.infrastructure.config; + +import net.createmod.catnip.config.ConfigBase; + +public class CReactorHeat extends ConfigBase { + public final ConfigInt size5Danger = i(256, 0, 8192, "size5Danger", "Heat threshold for DANGER level (5x5 reactor)"); + public final ConfigInt size7Danger = i(1024, 0, 8192, "size7Danger", "Heat threshold for DANGER level (7x7 reactor)"); + public final ConfigInt size9Danger = i(4096, 0, 8192, "size9Danger", "Heat threshold for DANGER level (9x9 reactor)"); + + @Override + public String getName() { + return "ReactorHeat"; + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CRods.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CRods.java index 947b9f4..ec7edcd 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CRods.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CRods.java @@ -1,22 +1,51 @@ package net.nuclearteam.createnuclear.infrastructure.config; import net.createmod.catnip.config.ConfigBase; +import net.minecraft.MethodsReturnNonnullByDefault; +@MethodsReturnNonnullByDefault public class CRods extends ConfigBase { - public final ConfigInt uraniumRodLifetime = i(3600, 100, 5000, "Uranium rod lifespan", Comments.UraniumRodLifetime, Comments.hintTick); - public final ConfigInt graphiteRodLifetime = i(3600, 100, 5000, "Graphite rod lifespan", Comments.GraphiteRodLifetime, Comments.hintTick); - public final ConfigInt maxHeat = i(1000, 200, 1000, "Maximum reactor heat", Comments.maxHeat, Comments.hintHeat); + public final ConfigInt uraniumRodLifetime = i(3600, 100, 5000, "uranium_rod_lifetime_ticks", Comments.uraniumRodLifetime, Comments.hintTick); + public final ConfigInt uraniumProximityBonus = i(32, -70, 70, "uranium_proximity_bonus", Comments.warning, Comments.uraniumProximityBonus); + public final ConfigInt uraniumBaseValue = i(64, -70, 70, "uranium_base_value", Comments.warning, Comments.uraniumBaseValue); + public final ConfigInt uraniumHeatRatio = i(2, -10, 10, "Heat ratio for uranium rods", Comments.warning, Comments.uraniumHeatRatio); + + public final ConfigInt graphiteRodLifetime = i(3600, 100, 5000, "graphite_rod_lifetime_ticks", Comments.graphiteRodLifetime, Comments.hintTick); + // the proximity value of coolant items are divisions so if the heat of the fuel is 64, the calcul will be "heat + 64/-4" + public final ConfigFloat graphiteProximityMalus = f(-0.25f, -70, 70, "graphite_proximity_penalty", Comments.warning, Comments.graphiteProximityMalus); + public final ConfigInt graphiteBaseValue = i(-32, -50, 50, "graphite_base_value", Comments.warning, Comments.graphiteBaseValue); + public final ConfigInt graphiteHeatRatio = i(1, -10, 10, "Heat ratio for graphite rods", Comments.warning, Comments.graphiteHeatRatio); + + public final ConfigInt thoriumRodLifetime = i(3600, 100, 5000, "Thorium rod lifetime (in ticks)", Comments.thoriumRodLifetime, Comments.hintTick); + public final ConfigInt thoriumProxyBonus = i(8, -70, 70, "Heat bonus from nearby thorium rods", Comments.warning, Comments.thoriumProximityBonus); + public final ConfigInt baseValueThorium = i(16, -70, 70, "Base heat value for thorium rods", Comments.warning, Comments.thoriumBaseValue); + public final ConfigInt thoriumHeatRatio = i(1, -10, 10, "Heat ratio for thorium rods", Comments.warning, Comments.thoriumHeatRatio); + @Override public String getName() { - return "Rods"; + return "rods"; } private static class Comments { static String hintTick = "20 ticks = 1 second"; - static String UraniumRodLifetime = "Uranium rod lifespan in reactor"; - static String GraphiteRodLifetime = "Graphite rod lifespan in reactor"; - static String maxHeat = "Maximum heat a reactor block can handle"; - static String hintHeat = "Avoids reactor failure due to excessive heat"; + static String warning = "Changing these values may unbalance reactor behavior."; + static String maxFuelPerCooled = "Maximum fuel rods supported by a single cooled rod"; + + static String uraniumRodLifetime = "Lifetime of uranium rods in ticks."; + static String uraniumProximityBonus = "Heat bonus applied when uranium rods are adjacent."; + static String uraniumBaseValue = "Base heat contribution of a uranium rod before modifiers."; + static String uraniumHeatRatio = "Heat ratio modifier for a uranium rod"; + + static String graphiteRodLifetime = "Lifetime of graphite (cooling) rods in ticks."; + static String graphiteProximityMalus = "Heat penalty applied when graphite rods are adjacent."; + static String graphiteBaseValue = "Base heat contribution of a graphite rod before modifiers."; + static String graphiteHeatRatio = "Heat ratio modifier for a graphite rod"; + + static String thoriumRodLifetime = "Lifetime of thorium rods in the reactor"; + static String thoriumProximityBonus = "Bonus heat applied when thorium rods are adjacent"; + static String thoriumBaseValue = "Base heat contribution of a thorium rod before modifiers"; + static String thoriumHeatRatio = "Heat ratio modifier for a thorium rod"; + } -} +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CWorldGen.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CWorldGen.java index ea7de34..e716179 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CWorldGen.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/config/CWorldGen.java @@ -3,7 +3,7 @@ import net.createmod.catnip.config.ConfigBase; public class CWorldGen extends ConfigBase { - public final ConfigBool disable = b(false, "disableWorldGen", Comments.disable); + public final ConfigBool enable = b(true, "enable_world_gen", Comments.enable); @Override public String getName() { @@ -11,6 +11,6 @@ public String getName() { } private static class Comments { - static String disable = "Prevents all worldgen added by Create from taking effect"; + static String enable = "When true, CreateNuclear world generation features are active. Set to false to disable all added ores/structures."; } -} +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CNDamageTypeTagsProvider.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CNDamageTypeTagsProvider.java new file mode 100644 index 0000000..a56e86f --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CNDamageTypeTagsProvider.java @@ -0,0 +1,36 @@ +package net.nuclearteam.createnuclear.infrastructure.data; + +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.PackOutput; +import net.minecraft.data.tags.TagsProvider; +import net.minecraft.tags.DamageTypeTags; +import net.minecraft.world.damagesource.DamageType; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import net.nuclearteam.createnuclear.CNDamageTypes; +import net.nuclearteam.createnuclear.CreateNuclear; + +import java.util.concurrent.CompletableFuture; + +// DamageType is a datapack registry: our entries (CNDamageTypes) only exist in the enriched +// HolderLookup.Provider produced by GeneratedEntriesProvider, not in Registrate's own lookup +// provider. That's why this is a plain TagsProvider wired manually in CreateNuclearDatagen, +// instead of a Registrate dynamic tag generator (which would fail validation, missing references). +public class CNDamageTypeTagsProvider extends TagsProvider { + public CNDamageTypeTagsProvider(PackOutput output, CompletableFuture lookupProvider, ExistingFileHelper existingFileHelper) { + super(output, Registries.DAMAGE_TYPE, lookupProvider, CreateNuclear.MOD_ID, existingFileHelper); + } + + @Override + protected void addTags(HolderLookup.Provider provider) { + tag(DamageTypeTags.NO_KNOCKBACK) + .add(CNDamageTypes.RADIATION) + .add(CNDamageTypes.FAN_RADIATION) + ; + } + + @Override + public String getName() { + return "CreateNuclear Damage Type Tags"; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CreateNuclearDatagen.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CreateNuclearDatagen.java index dc4c146..4b5e8ed 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CreateNuclearDatagen.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CreateNuclearDatagen.java @@ -2,8 +2,6 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.simibubi.create.foundation.data.recipe.CreateMechanicalCraftingRecipeGen; -import com.simibubi.create.foundation.data.recipe.CreateRecipeProvider; import com.simibubi.create.foundation.utility.FilesHelper; import com.tterrag.registrate.providers.ProviderType; import net.createmod.ponder.foundation.PonderIndex; @@ -12,11 +10,11 @@ import net.minecraft.data.PackOutput; import net.neoforged.neoforge.common.data.ExistingFileHelper; import net.neoforged.neoforge.data.event.GatherDataEvent; +import net.nuclearteam.createnuclear.CNSoundEvents; import net.nuclearteam.createnuclear.CreateNuclear; import net.nuclearteam.createnuclear.foundation.advancement.CNAdvancement; import net.nuclearteam.createnuclear.foundation.data.recipe.CNMechanicalCraftingRecipeGen; import net.nuclearteam.createnuclear.foundation.data.recipe.CNRecipeProvider; -import net.nuclearteam.createnuclear.foundation.data.recipe.CNShapelessRecipeGen; import net.nuclearteam.createnuclear.foundation.data.recipe.CNStandardRecipeGen; import net.nuclearteam.createnuclear.foundation.ponder.CreateNuclearPonderPlugin; @@ -47,10 +45,11 @@ public static void gatherData(GatherDataEvent event) { generator.addProvider(event.includeClient(), new CNStandardRecipeGen(output, lookupProvider)); generator.addProvider(event.includeServer(), new CNMechanicalCraftingRecipeGen(output, lookupProvider)); -// generator.addProvider(event.includeServer(), new CNShapelessRecipeGen(output, lookupProvider)); - generator.addProvider(event.includeClient(), new CNAdvancement(output, lookupProvider)); + generator.addProvider(event.includeServer(), new CNAdvancement(output, lookupProvider)); + generator.addProvider(event.includeClient(), CNSoundEvents.provider(generator)); + generator.addProvider(event.includeServer(), new CNDamageTypeTagsProvider(output, lookupProvider, existingFileHelper)); if (event.includeServer()) { CNRecipeProvider.registerAllProcessing(generator, output, lookupProvider); @@ -67,7 +66,9 @@ private static void addExtraRegistrateData() { provideDefaultLang("potion", langConsumer); provideDefaultLang("tooltips", langConsumer); provideDefaultLang("reactor", langConsumer); + provideDefaultLang("irradiated", langConsumer); CNAdvancement.provideLang(langConsumer); + CNSoundEvents.provideLang(langConsumer); providePonderLang(langConsumer); }); } diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CreateNuclearRegistrateTags.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CreateNuclearRegistrateTags.java index f4f6602..9f2ae25 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CreateNuclearRegistrateTags.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/CreateNuclearRegistrateTags.java @@ -9,6 +9,7 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.material.Fluid; import net.nuclearteam.createnuclear.CNBlocks; import net.nuclearteam.createnuclear.CNEntityType; @@ -42,6 +43,10 @@ private static void genBlockTags(RegistrateTagsProvider provIn) { .add(CNBlocks.ENRICHING_FIRE.get()) ; + prov.tag(CNBlockTags.FAN_PROCESSING_CATALYSTS_SNOW_POWDER.tag) + .add(Blocks.POWDER_SNOW) + ; + for (CNBlockTags tag : CNBlockTags.values()) { if (tag.alwaysDatagen) { prov.getOrCreateRawBuilder(tag.tag); @@ -71,6 +76,11 @@ private static void genFluidTags(RegistrateTagsProvider provIn) { ; + prov.tag(FluidTags.WATER) + .addTag(CNFluidTags.NITROGEN.tag) + ; + + for (CNFluidTags tag : CNFluidTags.values()) { if (tag.alwaysDatagen) { prov.getOrCreateRawBuilder(tag.tag); diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/GeneratedEntriesProvider.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/GeneratedEntriesProvider.java index 7ec248a..21b4d48 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/GeneratedEntriesProvider.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/GeneratedEntriesProvider.java @@ -9,9 +9,16 @@ import net.neoforged.neoforge.registries.NeoForgeRegistries; import net.nuclearteam.createnuclear.CNDamageTypes; import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.api.CreateNuclearRegistries; +import net.nuclearteam.createnuclear.content.multiblock.fluid.CNReactorFluidTypes; +import net.nuclearteam.createnuclear.content.multiblock.rod.CNRodTypes; import net.nuclearteam.createnuclear.infrastructure.worldgen.CNBiomeModifiers; import net.nuclearteam.createnuclear.infrastructure.worldgen.CNConfiguredFeatures; import net.nuclearteam.createnuclear.infrastructure.worldgen.CNPlacedFeatures; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNBiomes; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNDensityFunctions; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNNoiseData; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNNoiseGeneratorSettings; import java.util.Set; import java.util.concurrent.CompletableFuture; @@ -23,6 +30,12 @@ public class GeneratedEntriesProvider extends DatapackBuiltinEntriesProvider { .add(Registries.CONFIGURED_FEATURE, (RegistryBootstrap) CNConfiguredFeatures::bootstrap) .add(Registries.PLACED_FEATURE, CNPlacedFeatures::bootstrap) .add(NeoForgeRegistries.Keys.BIOME_MODIFIERS, CNBiomeModifiers::bootstrap) + .add(Registries.BIOME, CNBiomes::bootstrapRegistries) + .add(Registries.DENSITY_FUNCTION, CNDensityFunctions::bootstrapRegistries) + .add(Registries.NOISE_SETTINGS, CNNoiseGeneratorSettings::bootstrapRegistries) + .add(Registries.NOISE, CNNoiseData::bootstrapRegistries) + .add(CreateNuclearRegistries.ROD_TYPE, CNRodTypes::bootstrap) + .add(CreateNuclearRegistries.FLUID_TYPE, CNReactorFluidTypes::bootstrap) ; public GeneratedEntriesProvider(PackOutput output, CompletableFuture registries) { diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CNCreateNuclearPonderTags.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/ponder/CNCreateNuclearPonderTags.java similarity index 83% rename from src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CNCreateNuclearPonderTags.java rename to src/main/java/net/nuclearteam/createnuclear/infrastructure/ponder/CNCreateNuclearPonderTags.java index 2763f80..d1377d3 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/ponder/CNCreateNuclearPonderTags.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/ponder/CNCreateNuclearPonderTags.java @@ -1,4 +1,4 @@ -package net.nuclearteam.createnuclear.foundation.ponder; +package net.nuclearteam.createnuclear.infrastructure.ponder; import com.tterrag.registrate.util.entry.RegistryEntry; import net.createmod.catnip.registry.RegisteredObjectsHelper; @@ -8,6 +8,7 @@ import net.nuclearteam.createnuclear.CNBlocks; import net.nuclearteam.createnuclear.CreateNuclear; +import static com.simibubi.create.infrastructure.ponder.AllCreatePonderTags.DISPLAY_SOURCES; import static com.simibubi.create.infrastructure.ponder.AllCreatePonderTags.KINETIC_SOURCES; @@ -31,6 +32,10 @@ public static void register(PonderTagRegistrationHelper helper .add(CNBlocks.REACTOR_CONTROLLER) ; + HELPER.addToTag(DISPLAY_SOURCES) + .add(CNBlocks.REACTOR_CONTROLLER) + ; + } } diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/ponder/scenes/CNPonderReactorScenes.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/ponder/scenes/CNPonderReactorScenes.java new file mode 100644 index 0000000..755cb70 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/ponder/scenes/CNPonderReactorScenes.java @@ -0,0 +1,348 @@ +package net.nuclearteam.createnuclear.infrastructure.ponder.scenes; + +import net.createmod.catnip.math.Pointing; +import net.createmod.ponder.api.scene.SceneBuilder; +import net.createmod.ponder.api.scene.SceneBuildingUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.phys.Vec3; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.CNItems; +import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock; + +import java.util.HashMap; +import java.util.Map; + +public class CNPonderReactorScenes { + + // multiblock sizes and heights for tiers + private static final int S_T1 = 5; + private static final int H_T1 = 7; + private static final int S_T2 = 7; + private static final int H_T2 = 9; + private static final int S_T3 = 9; + private static final int H_T3 = 11; + + private static final int PEDESTAL_Y = 0; // pedestal layer (snow/concrete) + private static final int MULTIBLOCK_BASE_Y = 1; // multiblock starts at y=1 + private static final int MARGIN = 2; // Create margin + private static int plateSizeFor(int multiblockSize) { return multiblockSize + MARGIN * 2; } + + /** + * Simple container for storing all positions of interest for a multiblock. * The BlockPos values here must be in SCENE COORDINATES (0..plate-1 for X/Z, 1..H for Y). + */ + private record Positions(BlockPos controller, BlockPos input1, BlockPos input2, BlockPos liquidInput, + BlockPos alarm, BlockPos output) { + + /** + * All blocks that carry an explanatory callout, so a section-based reveal can show them per layer. + */ + BlockPos[] specials() { + return new BlockPos[]{controller, input1, input2, liquidInput, alarm, output}; + } + } + + /** Describes a single callout: its text and the direction to point at. */ + private record CalloutInfo(String text, Direction pointDirection, int fullDuration, int reducedDuration, int fullIdle, int reducedIdle) {} + + /** + * Static map of positions per multiblock size. + * Key = multiblockSize (5 for S_T1, 7 for S_T2, 9 for S_T3). + * Rule: x/z in 0..plate-1, y in 1..H; these values must match the structure's actual NBT layout. + */ + private static final Map STATIC_POS = new HashMap<>(); + static { + // Example for T1 (multiblockSize = 5) + // plate = 5 + 4 = 9 => valid x/z: 0..8; inner multiblock: 2..6 + STATIC_POS.put(5, new Positions( + new BlockPos(4, 4, 6), // controller + new BlockPos(3, 2, 6), // input1 + new BlockPos(3, 3, 6), // input2 + new BlockPos(3, 4, 6), // liquidInput + new BlockPos(5, 4, 6), // alarm + new BlockPos(5, 2, 6) // output + )); + + // Example for T2 (multiblockSize = 7) + STATIC_POS.put(7, new Positions( + new BlockPos(5, 5, 8), // controller + new BlockPos(3, 3, 8), // input1 + new BlockPos(3, 4, 8), // input2 + new BlockPos(3, 5, 8), // liquidInput + new BlockPos(7, 5, 8), // alarm + new BlockPos(7, 3, 8) // output + )); + + // Example for T3 (multiblockSize = 9) + STATIC_POS.put(9, new Positions( + new BlockPos(6, 6, 10), // controller + new BlockPos(5, 4, 10), // input1 + new BlockPos(5, 5, 10), // input2 + new BlockPos(5, 6, 10), // liquidInput + new BlockPos(7, 6, 10), // alarm + new BlockPos(7, 4, 10) // output + )); + } + + /** + * Precomputes a BlockPos -> CalloutInfo map for O(1) lookup per cell instead of + * iterating pos.specials() and comparing coordinates for every (x, y, z) visited. + */ + private static Map buildCallouts(Positions pos) { + Map callouts = new HashMap<>(); + callouts.put(pos.controller, new CalloutInfo( + "Controller: brain of the reactor, and the place where the blueprint goes to start it", + Direction.DOWN, + 130, 110, + 140, 120 + )); + + // Extend here if input1/input2/liquidInput/alarm/output ever need a callout + // during structure reveal (they currently don't have one — see ioPlacement() + // for their dedicated explanations). + return callouts; + } + + /** * Returns the static positions for the given size. * If no static entry exists, returns "reasonable" computed positions instead. */ + private static Positions positionsFor(int multiblockSize, int height) { + Positions p = STATIC_POS.get(multiblockSize); + if (p != null) return p; + + // fallback: simple centered calculation (avoids an NPE) + int plate = plateSizeFor(multiblockSize); + int offset = MARGIN; + int cx = offset + (multiblockSize / 2); + int cz = offset + (multiblockSize / 2); + int cy = MULTIBLOCK_BASE_Y + (height / 2); + return new Positions( + new BlockPos(cx, cy, cz), // controller + new BlockPos(cx, MULTIBLOCK_BASE_Y+1, offset + multiblockSize - 1), // input1 front + new BlockPos(cx, Math.min(MULTIBLOCK_BASE_Y+height-1, MULTIBLOCK_BASE_Y+2), offset + multiblockSize - 1), // input2 + new BlockPos(cx, cy, offset), // liquidInput back + new BlockPos(Math.max(offset, cx-1), cy, cz), // alarm + new BlockPos(offset + multiblockSize - 1, cy, cz) // output right + ); + } + + private static void showReactorStructure(SceneBuilder scene, SceneBuildingUtil util, int S, int H, int plate) { + showReactorStructure(scene, util, S, H, plate, false); + } + + /** + * @param bySections when true, each floor is revealed as a single render section instead of + * block-by-block. Block-by-block creates one {@code WorldSectionElement} per cell + * ({@code H * plate^2}, e.g. 1859 for T3) and they all keep rendering every frame, which + * is what makes the larger tiers lag past ~2/3 of the scene. T1/T2 stay block-by-block. + */ + private static void showReactorStructure(SceneBuilder scene, SceneBuildingUtil util, int S, int H, int plate, boolean bySections) { + Positions pos = positionsFor(S, H); + Map callouts = buildCallouts(pos); + + int minX = MARGIN; + int maxX = MARGIN + S - 1; + int minZ = MARGIN; + int maxZ = MARGIN + S - 1; + int minY = 1; + int maxY = H; + + scene.idle(20); + + for (int y = 1; y <= H; y++) { + scene.overlay().showText(bySections ? 25 : 8) + .text("Floor " + y) + .attachKeyFrame() + .placeNearTarget(); + + if (bySections) { + // One section for the whole floor: same visual build-up, a fraction of the draws. + scene.world().showSection(util.select().layer(y), Direction.NORTH); + // Block-by-block got its per-floor pacing from plate^2 * idle(4). With a single + // section per floor we must idle explicitly, otherwise callout-free floors flash + // by instantly and their "Floor N" labels overlap each other. + scene.idle(50); + for (Map.Entry entry : callouts.entrySet()) { + if (entry.getKey().getY() == y) { + showCallout(scene, util, entry.getKey(), entry.getValue(), bySections); + } + } + } else { + for (int x = 0; x < plate; x++) { + for (int z = 0; z < plate; z++) { + BlockPos cell = new BlockPos(x, y, z); + scene.world().showSection(util.select().position(x, y, z), Direction.NORTH); + scene.idle(4); + CalloutInfo info = callouts.get(cell); + if (info != null) { + showCallout(scene, util, cell, info, bySections); + } + } + } + } + } + + scene.idle(20); + scene.overlay() + .showText(110) + .text("To start the reactor you will need liquid and rods corresponding to the pattern, then right click the controller with the blueprint in hand"); + Vec3 topSide = util.vector().blockSurface(pos.controller, Direction.EAST); + scene.overlay() + .showControls(topSide, Pointing.UP, 60) + .withItem(CNItems.REACTOR_BLUEPRINT.asStack()) + .rightClick(); + scene.world().modifyBlock(pos.controller, s -> s.setValue(ReactorControllerBlock.ASSEMBLED, true), true); + + scene.idle(120); + scene.overlay() + .showText(120) + .text("Note: Check page 4 for I/O and Alarm blocks (placement & function).") + .attachKeyFrame() + .placeNearTarget(); + scene.idle(130); + } + + private static void showCallout(SceneBuilder scene, SceneBuildingUtil util, BlockPos at, CalloutInfo info, boolean reduced) { + scene.overlay().showText(reduced ? info.reducedDuration() : info.fullDuration()) + .text(info.text()) + .pointAt(util.vector().blockSurface(at, info.pointDirection())) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(reduced ? info.reducedIdle() : info.fullIdle()); + } + + public static void t1(SceneBuilder scene, SceneBuildingUtil util) { + int S = S_T1; + int plate = plateSizeFor(S); + scene.title("reactor_t1","Reactor T1"); + scene.configureBasePlate(0, 0, plate); + scene.world().showSection(util.select().layer(0), Direction.UP); + scene.showBasePlate(); + scene.rotateCameraY(180); + scene.scaleSceneView(0.55f); + showReactorStructure(scene, util, S, H_T1, plate, true); + } + + public static void t2(SceneBuilder scene, SceneBuildingUtil util) { + int S = S_T2; + int plate = plateSizeFor(S); + scene.title("reactor_t2","Reactor T2"); + scene.configureBasePlate(0, 0, plate); + scene.world().showSection(util.select().layer(0), Direction.UP); + scene.showBasePlate(); + scene.rotateCameraY(180); + scene.scaleSceneView(0.45f); + showReactorStructure(scene, util, S, H_T2, plate, true); + } + + public static void t3(SceneBuilder scene, SceneBuildingUtil util) { + int S = S_T3; + int plate = plateSizeFor(S); + scene.title("reactor_t3","Reactor T3"); + scene.configureBasePlate(0, 0, plate); + scene.world().showSection(util.select().layer(0), Direction.UP); + scene.showBasePlate(); + scene.rotateCameraY(180); + scene.scaleSceneView(0.35f); + // T3 reveals floor-by-floor (section-based) so the largest tier doesn't lag; T1/T2 stay block-by-block. + showReactorStructure(scene, util, S, H_T3, plate, true); + } + + public static void ioPlacement(SceneBuilder scene, SceneBuildingUtil util) { + int S = S_T1; + int plate = plateSizeFor(S); + Positions pos = positionsFor(S, H_T1); + + scene.title("reactor_io_placement", "Reactor I/O: Function & Placement"); + scene.configureBasePlate(0, 0, plate); + scene.world().showSection(util.select().layer(0), Direction.UP); + scene.showBasePlate(); + scene.rotateCameraY(180); + scene.scaleSceneView(0.55f); + + // Populate the correct I/O blocks at the beginning because the schematic has old broken IDs + scene.world().modifyBlock(pos.input1, s -> CNBlocks.REACTOR_ROD_INPUT.get().defaultBlockState().setValue(BlockStateProperties.FACING, Direction.SOUTH), false); + scene.world().modifyBlock(pos.input2, s -> CNBlocks.REACTOR_ROD_INPUT.get().defaultBlockState().setValue(BlockStateProperties.FACING, Direction.SOUTH), false); + scene.world().modifyBlock(pos.liquidInput, s -> CNBlocks.REACTOR_FLUID_INPUT.get().defaultBlockState().setValue(BlockStateProperties.FACING, Direction.SOUTH), false); + scene.world().modifyBlock(pos.alarm, s -> CNBlocks.REACTOR_ALARM.get().defaultBlockState(), false); + scene.world().modifyBlock(pos.output, s -> CNBlocks.REACTOR_OUTPUT.get().defaultBlockState().setValue(BlockStateProperties.FACING, Direction.SOUTH), false); + + // Show the entire T1 structure instantly + scene.world().showSection(util.select().layersFrom(1), Direction.UP); + scene.idle(20); + + // Show Input 1 + scene.overlay().showText(150) + .text("Rod Input: Stores Heating or Cooling Rods. We need one Heating Rod (fuel) to heat the reactor, and one Cooling Rod for stability.") + .pointAt(util.vector().blockSurface(pos.input1, Direction.SOUTH)) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(160); + + // Show Input 2 + scene.overlay().showText(150) + .text("Second Rod Input: This is why we need at least two inputs! One for the Heating Rod and one for the Cooling Rod to prevent explosions.") + .pointAt(util.vector().blockSurface(pos.input2, Direction.SOUTH)) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(160); + + // Show Fluid Input + scene.overlay().showText(150) + .text("Fluid Input: Fluid is also required to cool the reactor and ensure it does not explode.") + .pointAt(util.vector().blockSurface(pos.liquidInput, Direction.SOUTH)) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(160); + + // Show Alarm + scene.overlay().showText(150) + .text("Alarm (Optional): Emits a sound when the reactor becomes unstable and risks exploding.") + .pointAt(util.vector().blockSurface(pos.alarm, Direction.SOUTH)) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(160); + + // Show Output + scene.overlay().showText(160) + .text("Output: Necessary to extract generated energy. You can place multiple outputs to dispatch the total energy between them.") + .pointAt(util.vector().blockSurface(pos.output, Direction.SOUTH)) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(170); + + // --- Placement --- + scene.overlay().showText(120) + .text("These blocks can replace ANY Reactor Casing, as long as it is not on an edge.") + .attachKeyFrame() + .placeNearTarget(); + scene.idle(130); + + // Demonstrate moving the blocks to the roof (y=7 for T1) + BlockPos newIn1 = new BlockPos(3, 7, 3); + BlockPos newIn2 = new BlockPos(3, 7, 4); + BlockPos newLiq = new BlockPos(3, 7, 5); + BlockPos newAlm = new BlockPos(5, 7, 3); + BlockPos newOut = new BlockPos(5, 7, 5); + + // Replace old pos with casing + scene.world().modifyBlock(pos.input1, s -> CNBlocks.REACTOR_CASING.get().defaultBlockState(), true); + scene.world().modifyBlock(pos.input2, s -> CNBlocks.REACTOR_CASING.get().defaultBlockState(), true); + scene.world().modifyBlock(pos.liquidInput, s -> CNBlocks.REACTOR_CASING.get().defaultBlockState(), true); + scene.world().modifyBlock(pos.alarm, s -> CNBlocks.REACTOR_CASING.get().defaultBlockState(), true); + scene.world().modifyBlock(pos.output, s -> CNBlocks.REACTOR_CASING.get().defaultBlockState(), true); + + // Place I/O on roof + scene.world().modifyBlock(newIn1, s -> CNBlocks.REACTOR_ROD_INPUT.get().defaultBlockState().setValue(BlockStateProperties.FACING, Direction.UP), true); + scene.world().modifyBlock(newIn2, s -> CNBlocks.REACTOR_ROD_INPUT.get().defaultBlockState().setValue(BlockStateProperties.FACING, Direction.UP), true); + scene.world().modifyBlock(newLiq, s -> CNBlocks.REACTOR_FLUID_INPUT.get().defaultBlockState().setValue(BlockStateProperties.FACING, Direction.UP), true); + // Note: ReactorAlarm might not have FACING. Using default state. + scene.world().modifyBlock(newAlm, s -> CNBlocks.REACTOR_ALARM.get().defaultBlockState(), true); + scene.world().modifyBlock(newOut, s -> CNBlocks.REACTOR_OUTPUT.get().defaultBlockState().setValue(BlockStateProperties.FACING, Direction.UP), true); + + scene.overlay().showText(100) + .text("They can be grouped together on the roof or any other flat surface.") + .pointAt(util.vector().blockSurface(newIn2, Direction.UP)) + .placeNearTarget(); + scene.idle(110); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNBiomeModifiers.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNBiomeModifiers.java index 3d593d0..96db209 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNBiomeModifiers.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNBiomeModifiers.java @@ -1,6 +1,5 @@ package net.nuclearteam.createnuclear.infrastructure.worldgen; -import com.simibubi.create.infrastructure.worldgen.AllPlacedFeatures; import net.minecraft.core.Holder; import net.minecraft.core.HolderGetter; import net.minecraft.core.HolderSet; @@ -20,6 +19,8 @@ public class CNBiomeModifiers { public static final ResourceKey URANIUM_ORE = key("uranium_ore"), LEAD_ORE = key("lead_ore"), + THORIUM_ORE = key("thorium_ore"), + NITRATE_ORE = key("nitrate_ore"), STRIATED_ORES_OVERWORLD = key("striated_ores_overworld") ; @@ -34,10 +35,14 @@ public static void bootstrap(BootstrapContext ctx) { HolderGetter featureLookup = ctx.lookup(Registries.PLACED_FEATURE); Holder uraniumOre = featureLookup.getOrThrow(CNPlacedFeatures.URANIUM_ORE); Holder leadOre = featureLookup.getOrThrow(CNPlacedFeatures.LEAD_ORE); + Holder thoriumOre = featureLookup.getOrThrow(CNPlacedFeatures.THORIUM_ORE); + Holder nitrateOre = featureLookup.getOrThrow(CNPlacedFeatures.NITRATE_ORE); Holder striatedOresOverworld = featureLookup.getOrThrow(CNPlacedFeatures.STRIATED_ORES_OVERWORLD); ctx.register(URANIUM_ORE, addOre(isOverworld, uraniumOre)); ctx.register(LEAD_ORE, addOre(isOverworld, leadOre)); + ctx.register(THORIUM_ORE, addOre(isOverworld, thoriumOre)); + ctx.register(NITRATE_ORE, addOre(isOverworld, nitrateOre)); ctx.register(STRIATED_ORES_OVERWORLD, addOre(isOverworld, striatedOresOverworld)); } diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNConfiguredFeatures.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNConfiguredFeatures.java index 4ef17fa..2fb2767 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNConfiguredFeatures.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNConfiguredFeatures.java @@ -23,6 +23,8 @@ public class CNConfiguredFeatures { public static final ResourceKey> URANIUM_ORE = key("uranium_ore"), LEAD_ORE = key("lead_ore"), + THORIUM_ORE = key("thorium_ore"), + NITRATE_ORE = key("nitrate_ore"), STRIATED_ORES_OVERWORLD = key("striated_ores_overworld") ; @@ -38,15 +40,25 @@ public static void bootstrap(BootstrapContext> ctx) { OreConfiguration.target(stoneOreReplaceable, CNBlocks.URANIUM_ORE.getDefaultState()), OreConfiguration.target(deepslateOreReplaceables, CNBlocks.DEEPSLATE_URANIUM_ORE.getDefaultState()) ); - register(ctx, URANIUM_ORE, Feature.ORE, new OreConfiguration(uraniumTargetStates, 7)); List leadTargetStates = List.of( OreConfiguration.target(stoneOreReplaceable, CNBlocks.LEAD_ORE.getDefaultState()), OreConfiguration.target(deepslateOreReplaceables, CNBlocks.DEEPSLATE_LEAD_ORE.getDefaultState()) ); + register(ctx, LEAD_ORE, Feature.ORE, new OreConfiguration(leadTargetStates, 12)); + + List thoriumTargetStates = List.of( + OreConfiguration.target(stoneOreReplaceable, CNBlocks.THORIUM_ORE.getDefaultState()), + OreConfiguration.target(deepslateOreReplaceables, CNBlocks.DEEPSLATE_THORIUM_ORE.getDefaultState()) + ); + register(ctx, THORIUM_ORE, Feature.ORE, new OreConfiguration(thoriumTargetStates, 12)); - register(ctx, LEAD_ORE, Feature.ORE, new OreConfiguration(leadTargetStates, 7)); + List nitrateTargetStates = List.of( + OreConfiguration.target(stoneOreReplaceable, CNBlocks.NITRATE_ORE.getDefaultState()), + OreConfiguration.target(deepslateOreReplaceables, CNBlocks.DEEPSLATE_NITRATE_ORE.getDefaultState()) + ); + register(ctx, NITRATE_ORE, Feature.ORE, new OreConfiguration(nitrateTargetStates, 10)); List overworldLayerPatterns = List.of( CNLayerPatterns.AUTUNITE.get() diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNPlacedFeatures.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNPlacedFeatures.java index 4647131..ad0fe99 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNPlacedFeatures.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNPlacedFeatures.java @@ -1,6 +1,5 @@ package net.nuclearteam.createnuclear.infrastructure.worldgen; -import com.simibubi.create.infrastructure.worldgen.ConfigPlacementFilter; import net.minecraft.core.Holder; import net.minecraft.core.HolderGetter; import net.minecraft.core.registries.Registries; @@ -19,6 +18,8 @@ public class CNPlacedFeatures { public static final ResourceKey URANIUM_ORE = key("uranium_ore"), LEAD_ORE = key("lead_ore"), + THORIUM_ORE = key("thorium_ore"), + NITRATE_ORE = key("nitrate_ore"), STRIATED_ORES_OVERWORLD = key("striated_ores_overworld") ; @@ -30,11 +31,15 @@ public static void bootstrap(BootstrapContext ctx) { HolderGetter> featureLookup = ctx.lookup(Registries.CONFIGURED_FEATURE); Holder> uraniumOre = featureLookup.getOrThrow(CNConfiguredFeatures.URANIUM_ORE); Holder> leadOre = featureLookup.getOrThrow(CNConfiguredFeatures.LEAD_ORE); + Holder> thoriumOre = featureLookup.getOrThrow(CNConfiguredFeatures.THORIUM_ORE); + Holder> nitrateOre = featureLookup.getOrThrow(CNConfiguredFeatures.NITRATE_ORE); Holder> striatedOresOverworld = featureLookup.getOrThrow(CNConfiguredFeatures.STRIATED_ORES_OVERWORLD); - register(ctx, URANIUM_ORE, uraniumOre, placementOres(CountPlacement.of(6), -64, 64)); - register(ctx, LEAD_ORE, leadOre, placementOres(CountPlacement.of(6), -64, 64)); - register(ctx, STRIATED_ORES_OVERWORLD, striatedOresOverworld, placement(RarityFilter.onAverageOnceEvery(18), -30, 70)); + register(ctx, URANIUM_ORE, uraniumOre, placementOres(CountPlacement.of(4), -63, 16)); + register(ctx, LEAD_ORE, leadOre, placementOres(CountPlacement.of(10), -16, 60)); + register(ctx, THORIUM_ORE, thoriumOre, placementOres(CountPlacement.of(6), -16, 55)); + register(ctx, NITRATE_ORE, nitrateOre, placementOres(CountPlacement.of(6), -63, 64)); + register(ctx, STRIATED_ORES_OVERWORLD, striatedOresOverworld, placement(RarityFilter.onAverageOnceEvery(64), -63, 16)); } diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNPlacementModifiers.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNPlacementModifiers.java new file mode 100644 index 0000000..c940802 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/CNPlacementModifiers.java @@ -0,0 +1,18 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen; + +import net.minecraft.core.registries.Registries; +import net.minecraft.world.level.levelgen.placement.PlacementModifierType; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; +import net.nuclearteam.createnuclear.CreateNuclear; + +public class CNPlacementModifiers { + private static final DeferredRegister> REGISTER = DeferredRegister.create(Registries.PLACEMENT_MODIFIER_TYPE, CreateNuclear.MOD_ID); + + public static final DeferredHolder, PlacementModifierType> CONFIG_FILTER = REGISTER.register("config_filter", () -> () -> ConfigPlacementFilter.CODEC); + + public static void register(IEventBus modEventBus) { + REGISTER.register(modEventBus); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/ConfigPlacementFilter.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/ConfigPlacementFilter.java new file mode 100644 index 0000000..b727387 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/ConfigPlacementFilter.java @@ -0,0 +1,24 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen; + +import com.mojang.serialization.MapCodec; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.levelgen.placement.PlacementContext; +import net.minecraft.world.level.levelgen.placement.PlacementFilter; +import net.minecraft.world.level.levelgen.placement.PlacementModifierType; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; + +public class ConfigPlacementFilter extends PlacementFilter { + public static final ConfigPlacementFilter INSTANCE = new ConfigPlacementFilter(); + public static final MapCodec CODEC = MapCodec.unit(() -> INSTANCE); + + @Override + protected boolean shouldPlace(PlacementContext pContext, RandomSource pRandom, BlockPos pPos) { + return CNConfigs.common().worldGen.enable.get(); + } + + @Override + public PlacementModifierType type() { + return CNPlacementModifiers.CONFIG_FILTER.get(); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/BiomeIrradiationMapping.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/BiomeIrradiationMapping.java new file mode 100644 index 0000000..210c5e3 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/BiomeIrradiationMapping.java @@ -0,0 +1,8 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.biome.Biome; + +public record BiomeIrradiationMapping(TagKey sourceTag, ResourceKey target) { +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/BiomeIrradiationMappings.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/BiomeIrradiationMappings.java new file mode 100644 index 0000000..8a3a049 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/BiomeIrradiationMappings.java @@ -0,0 +1,28 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.level.biome.Biome; + +import java.util.List; + +public class BiomeIrradiationMappings { + private static final List MAPPINGS = List.of( + new BiomeIrradiationMapping(BiomeTags.IS_OVERWORLD, CNBiomes.Irradiated.PLAIN), + new BiomeIrradiationMapping(BiomeTags.IS_NETHER, CNBiomes.Irradiated.PLAIN), + new BiomeIrradiationMapping(BiomeTags.IS_END, CNBiomes.Irradiated.PLAIN) + ); + + private BiomeIrradiationMappings() {} + + public static ResourceKey resolveTarget(Holder currentBiome, ResourceKey fallback) { + for (BiomeIrradiationMapping mapping : MAPPINGS) { + if (currentBiome.is(mapping.sourceTag())) { + return mapping.target(); + } + } + + return fallback; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/BiomeIrradiationService.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/BiomeIrradiationService.java new file mode 100644 index 0000000..91158db --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/BiomeIrradiationService.java @@ -0,0 +1,120 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.SectionPos; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeResolver; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.infrastructure.config.CNConfigs; + +import java.util.ArrayList; +import java.util.List; + +public final class BiomeIrradiationService { + public static void circularArea(ServerLevel serverLevel, BlockPos center, ResourceKey defaultTarget, int radius) { + Registry biomeRegistry = serverLevel.registryAccess().registryOrThrow(Registries.BIOME); + + Holder currentAtCenter = serverLevel.getBiome(center); + ResourceKey targetAtCenter = BiomeIrradiationMappings.resolveTarget(currentAtCenter, defaultTarget); + if (currentAtCenter.is(targetAtCenter)) { + return; + } + + int minX = center.getX() - radius; + int maxX = center.getX() + radius; + int minZ = center.getZ() - radius; + int maxZ = center.getZ() + radius; + + double radiusSq = radius * radius; + BiomeResolver resolver = createCircularResolver(biomeRegistry, center, radiusSq, defaultTarget, serverLevel); + + List chunks = new ArrayList<>(); + for (int cz = SectionPos.blockToSectionCoord(minZ); cz < SectionPos.blockToSectionCoord(maxZ); ++cz) { + for (int cx = SectionPos.blockToSectionCoord(minX); cx < SectionPos.blockToSectionCoord(maxX); ++cx) { + ChunkAccess chunkAccess = serverLevel.getChunk(cx, cz, ChunkStatus.FULL, false); + if (chunkAccess != null) { + chunkAccess.fillBiomesFromNoise(resolver, serverLevel.getChunkSource().randomState().sampler()); + chunkAccess.setUnsaved(true); + chunks.add(chunkAccess); + } + } + } + + PersistentIrradiatedZones.get(serverLevel).addChunks(chunks.stream().map(ChunkAccess::getPos).toList()); + serverLevel.getChunkSource().chunkMap.resendBiomesForChunks(chunks); + } + + public static boolean restoreArea(ServerLevel serverLevel, BlockPos pos) { + ChunkPos centerChunk = new ChunkPos(pos); + PersistentIrradiatedZones zones = PersistentIrradiatedZones.get(serverLevel); + + List restored = new ArrayList<>(); + for (ChunkPos target : resolveRestoreTargets(centerChunk)) { + if (!zones.containsChunk(target)) continue; + + ChunkAccess chunkAccess = serverLevel.getChunk(target.x, target.z, ChunkStatus.FULL, false); + if (chunkAccess == null) continue; + + BiomeResolver resolver = (x, y, z, sample) -> serverLevel.getChunkSource().getGenerator().getBiomeSource().getNoiseBiome(x, y, z, sample); + + chunkAccess.fillBiomesFromNoise(resolver, serverLevel.getChunkSource().randomState().sampler()); + chunkAccess.setUnsaved(true); + restored.add(chunkAccess); + + zones.removeChunk(target); + } + + if (restored.isEmpty()) return false; + + serverLevel.getChunkSource().chunkMap.resendBiomesForChunks(restored); + + return true; + } + + private static List resolveRestoreTargets(ChunkPos center) { + if (!CNConfigs.server().biomeRestore.restoreInCircle.get()) { + return List.of(center); + } + + int radius = CNConfigs.server().biomeRestore.restoreRadiusChunks.get(); + List targets = new ArrayList<>(); + for (int dz = -radius; dz <= radius; dz++) { + for (int dx = -radius; dx <= radius; dx++) { + if (dx * dx + dz * dz <= radius * radius) { + targets.add(new ChunkPos(center.x + dx, center.z + dz)); + } + } + } + + return targets; + } + + private static BiomeResolver createCircularResolver(Registry biomeRegistry, BlockPos center, double radiusSq, ResourceKey defaultTarget, ServerLevel level) { + return (x, y, z, noise) -> { + int blockX = x << 2; + int blockZ = z << 2; + + double distX = blockX - center.getX(); + double distZ = blockZ - center.getZ(); + + Holder current = level.getBiome(new BlockPos(blockX, y << 2, blockZ)); + + if ((distX * distX) + (distZ * distZ) <= radiusSq) { + ResourceKey target = BiomeIrradiationMappings.resolveTarget(current, defaultTarget); + + return biomeRegistry.getHolderOrThrow(target); + } + + return current; + }; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNBiomes.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNBiomes.java new file mode 100644 index 0000000..6bd1c75 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNBiomes.java @@ -0,0 +1,29 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.level.biome.*; +import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.nuclearteam.createnuclear.CreateNuclear; +import org.jetbrains.annotations.NotNull; + +public class CNBiomes { + public static final class Irradiated { + public static final ResourceKey PLAIN = key("irradiated_land"); + } + + public static void bootstrapRegistries(BootstrapContext context) { + HolderGetter featureLookup = context.lookup(Registries.PLACED_FEATURE); + HolderGetter> carverLookup = context.lookup(Registries.CONFIGURED_CARVER); + HolderGetter soundLookup = context.lookup(Registries.SOUND_EVENT); + context.register(Irradiated.PLAIN, IrradiatedBiomes.createPlain(featureLookup, carverLookup, soundLookup)); + } + + public static @NotNull ResourceKey key(String id) { + return ResourceKey.create(Registries.BIOME, CreateNuclear.asResource(id)); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNDensityFunctions.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNDensityFunctions.java new file mode 100644 index 0000000..082a4d0 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNDensityFunctions.java @@ -0,0 +1,41 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.levelgen.DensityFunction; +import net.minecraft.world.level.levelgen.DensityFunctions; +import net.minecraft.world.level.levelgen.synth.BlendedNoise; +import net.nuclearteam.createnuclear.CreateNuclear; + +public class CNDensityFunctions { + public static final class Irradiated { + public static final ResourceKey EROSION = createKey("irradiated/erosion"); + public static final ResourceKey FINAL_DENSITY = createKey("irradiated/final_density"); + } + + private static ResourceKey createKey(String id) { + return ResourceKey.create(Registries.DENSITY_FUNCTION, CreateNuclear.asResource(id)); + } + + public static void bootstrapRegistries(BootstrapContext context) { + context.register(Irradiated.EROSION, DensityFunctions.add( + DensityFunctions.yClampedGradient(0, 90, 1, -1), + BlendedNoise.createUnseeded(0.25, 0.375, 80.0, 160.0, 8.0) + )); + + context.register(Irradiated.FINAL_DENSITY, DensityFunctions.add( + DensityFunctions.yClampedGradient(0, 90, 1, -1), + BlendedNoise.createUnseeded(0.25, 0.375, 80.0, 160.0, 8.0) + )); + } + + private static DensityFunction registerAndWrap(BootstrapContext context, ResourceKey key, DensityFunction densityFunction) { + return new DensityFunctions.HolderHolder(context.register(key, densityFunction)); + } + + public static DensityFunction getFunction(HolderGetter densityFunctions, ResourceKey key) { + return new DensityFunctions.HolderHolder(densityFunctions.getOrThrow(key)); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseData.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseData.java new file mode 100644 index 0000000..a245d57 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseData.java @@ -0,0 +1,29 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.levelgen.synth.NormalNoise.NoiseParameters; +import net.nuclearteam.createnuclear.CreateNuclear; + +public class CNNoiseData { + public static final ResourceKey EROSION = createKey("irradiated/erosion"); + + private static ResourceKey createKey(String id) { + return ResourceKey.create(Registries.NOISE, CreateNuclear.asResource(id)); + } + + public static void bootstrapRegistries(BootstrapContext context) { + register(context, EROSION, -9, 1.0, 1.0, 0.0, 1.0, 1.0); + } + + private static void register( + BootstrapContext context, + ResourceKey key, + int firstOctave, + double amplitude, + double... otherAmplitudes + ) { + context.register(key, new NoiseParameters(firstOctave, amplitude, otherAmplitudes)); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseGeneratorSettings.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseGeneratorSettings.java new file mode 100644 index 0000000..42e222c --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseGeneratorSettings.java @@ -0,0 +1,99 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.biome.OverworldBiomeBuilder; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.*; +import net.minecraft.world.level.levelgen.synth.NormalNoise; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.surfacerule.IrradiatedSurfaceRules; +import org.jetbrains.annotations.NotNull; + +public class CNNoiseGeneratorSettings { + public static final ResourceKey IRRADIATED = key("irradiated_noise"); + + public static void bootstrapRegistries(BootstrapContext context) { + HolderGetter densityLookup = context.lookup(Registries.DENSITY_FUNCTION); + HolderGetter noiseLookup = context.lookup(Registries.NOISE); + + context.register(IRRADIATED, new NoiseGeneratorSettings( + NoiseSettings.create(-32, 256, 1, 2), + CNBlocks.STEEL_BLOCK.get().defaultBlockState(), + Blocks.AIR.defaultBlockState(), + CNNoiseGeneratorSettings.irradiated(densityLookup, noiseLookup), + IrradiatedSurfaceRules.DEFAULT_RULE, + new OverworldBiomeBuilder().spawnTarget(), + 32, + false, + false, + false, + false + )); + } + + public static NoiseRouter irradiated(HolderGetter densityLookup, HolderGetter noiseLookup) { + DensityFunction shiftX = CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.SHIFT_X); + DensityFunction shiftZ = CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.SHIFT_Z); + DensityFunction y = CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.Y); + return new NoiseRouter( + DensityFunctions.constant(1), // barrierNoise + DensityFunctions.zero(), // fluidLevelFloodednessNoise + DensityFunctions.zero(), // fluidLevelSpreadNoise + DensityFunctions.zero(), // lavaNoise + DensityFunctions.shiftedNoise2d( + shiftX, shiftZ, 0.25, noiseLookup.getOrThrow(Noises.TEMPERATURE) + ), // temperature + DensityFunctions.shiftedNoise2d( + shiftX, shiftZ, 0, noiseLookup.getOrThrow(Noises.VEGETATION) + ), // vegetation + CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.CONTINENTS), // continents + CNDensityFunctions.getFunction(densityLookup, CNDensityFunctions.Irradiated.EROSION), // erosion + CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.DEPTH), // depth + CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.RIDGES), // ridges + DensityFunctions.add( + DensityFunctions.constant(0.1171875), + DensityFunctions.mul( + DensityFunctions.yClampedGradient( + -30, -40, 0, 1 + ), + DensityFunctions.add( + DensityFunctions.constant(-0.1171875), + DensityFunctions.add( + DensityFunctions.constant(-0.078125), + DensityFunctions.mul( + DensityFunctions.yClampedGradient( + 240, 256, 1, 0 + ), + DensityFunctions.add( + DensityFunctions.constant(0.078125), + DensityFunctions.add( + DensityFunctions.constant(-0.703125), + DensityFunctions.mul( + DensityFunctions.constant(4), + DensityFunctions.mul( + CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.DEPTH), + DensityFunctions.cache2d(CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.FACTOR)) + ).quarterNegative() + ) + ).clamp(-30, 64) + ) + ) + ) + ) + ) + ), // initialDensityWithoutJaggedness + DensityFunctions.blendDensity(CNDensityFunctions.getFunction(densityLookup, CNDensityFunctions.Irradiated.FINAL_DENSITY)), // finalDensity + DensityFunctions.zero(), // veinToggle + DensityFunctions.zero(), // veinRidged + DensityFunctions.zero() // veinGap + ); + } + + private static @NotNull ResourceKey key(String id) { + return ResourceKey.create(Registries.NOISE_SETTINGS, CreateNuclear.asResource(id)); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/IrradiatedBiomes.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/IrradiatedBiomes.java new file mode 100644 index 0000000..69cbc7c --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/IrradiatedBiomes.java @@ -0,0 +1,57 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.level.biome.*; +import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.nuclearteam.createnuclear.CNSoundEvents; +import net.nuclearteam.createnuclear.content.particles.IrradiatedParticlesData; + +public class IrradiatedBiomes { + public static Biome createPlain(HolderGetter featureLookup, HolderGetter> carverLookup, HolderGetter soundLookup) { + return IrradiatedBiomes.irradiated(featureLookup, carverLookup, soundLookup, new BiomeGenerationSettings.Builder(featureLookup, carverLookup)); + } + + public static Biome irradiated(HolderGetter featureGetter, HolderGetter> carverGetter, HolderGetter soundLookup, BiomeGenerationSettings.Builder generation) { + MobSpawnSettings.Builder spawnBuilder = new MobSpawnSettings.Builder(); + BiomeSpecialEffects.Builder effectBuilder = new BiomeSpecialEffects.Builder(); + + effectBuilder + // Water: murky green + .waterColor(0x3B5133) + .waterFogColor(0x0A0E0A) + + // Fog: sickly radioactive green (kept bright so it stays visible) + .fogColor(0x485E3E) + + // Sky: washed-out grey-green (still lets the sun/moon and day-night cycle show through) + .skyColor(0x324132) + + // Grass: sulfur yellow / scorched + .grassColorOverride(0x8C8F5B) + + // Foliage: withered olive + .foliageColorOverride(0x565E3E) + + .ambientParticle(new AmbientParticleSettings(new IrradiatedParticlesData(), 0.025F)) + .ambientMoodSound(AmbientMoodSettings.LEGACY_CAVE_SETTINGS) + // Plays continuously for as long as the player stands in the biome, under the + // Ambient/Environment volume slider. Deliberately NOT also set as .backgroundMusic(): + // that would start a second, unsynchronised copy of the same file in the MUSIC + // category, and the two would phase against each other. + .ambientLoopSound(soundLookup.getOrThrow(ResourceKey.create(Registries.SOUND_EVENT, CNSoundEvents.BIOME_WASTELAND.getId()))) + ; + + return new Biome.BiomeBuilder() + .mobSpawnSettings(spawnBuilder.build()) + .hasPrecipitation(false) + .temperature(2.0f) + .downfall(0f) + .specialEffects(effectBuilder.build()) + .generationSettings(generation.build()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/PersistentIrradiatedZones.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/PersistentIrradiatedZones.java new file mode 100644 index 0000000..87d299d --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/PersistentIrradiatedZones.java @@ -0,0 +1,81 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.datafix.DataFixTypes; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.saveddata.SavedData; +import net.nuclearteam.createnuclear.CreateNuclear; +import org.jetbrains.annotations.NotNull; + +import java.util.HashSet; +import java.util.Set; + +public class PersistentIrradiatedZones extends SavedData { + private static final String DATA = String.join("_", CreateNuclear.MOD_ID, "irradiated", "zones"); + + private final Set chunks = new HashSet<>(); + + public static PersistentIrradiatedZones get(ServerLevel level) { + return level.getDataStorage().computeIfAbsent(factory(), DATA); + } + + private static SavedData.Factory factory() { + return new SavedData.Factory<>(PersistentIrradiatedZones::new, PersistentIrradiatedZones::load, DataFixTypes.LEVEL); + } + + public void addChunks(Iterable newChunks) { + boolean changed = false; + for (ChunkPos pos : newChunks) { + changed |= chunks.add(pos); + } + + if (changed) setDirty(); + } + + public boolean isInsideAnyZone(BlockPos pos) { + return chunks.contains(new ChunkPos(pos)); + } + + public boolean containsChunk(ChunkPos pos) { + return chunks.contains(pos); + } + + public void removeChunk(ChunkPos pos) { + if (chunks.remove(pos)) setDirty(); + } + + public static PersistentIrradiatedZones load(CompoundTag nbt, HolderLookup.Provider registries) { + PersistentIrradiatedZones data = new PersistentIrradiatedZones(); + data.readFrom(nbt); + + return data; + } + + public void readFrom(CompoundTag nbt) { + chunks.clear(); + ListTag list = nbt.getList("chunks", Tag.TAG_COMPOUND); + list.forEach(tag -> { + CompoundTag e = (CompoundTag) tag; + + chunks.add(new ChunkPos(e.getInt("x"), e.getInt("z"))); + }); + } + + @Override + public @NotNull CompoundTag save(CompoundTag nbt, HolderLookup.@NotNull Provider registries) { + ListTag list = new ListTag(); + chunks.forEach(pos -> { + CompoundTag e = new CompoundTag(); + e.putInt("x", pos.x); + e.putInt("z", pos.z); + list.add(e); + }); + nbt.put("chunks", list); + return nbt; + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/BiomeTagRule.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/BiomeTagRule.java new file mode 100644 index 0000000..b25ed40 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/BiomeTagRule.java @@ -0,0 +1,47 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome.surfacerule; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.registries.Registries; +import net.minecraft.tags.TagKey; +import net.minecraft.util.KeyDispatchDataCodec; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.neoforged.neoforge.registries.RegisterEvent; +import net.nuclearteam.createnuclear.CreateNuclear; +import org.jetbrains.annotations.NotNull; + +public record BiomeTagRule(@NotNull TagKey tag) implements SurfaceRules.ConditionSource { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(TagKey.codec(Registries.BIOME).fieldOf("tag").forGetter(rule -> rule.tag)).apply(instance, BiomeTagRule::new)); + + /** + * A custom {@link SurfaceRules.ConditionSource} is only usable once its codec lives in the + * {@code MATERIAL_CONDITION} dispatch registry; without this, (de)serialising any rule that + * contains a BiomeTagRule fails with "Unregistered type in dispatch codec". + */ + public static void register(@NotNull RegisterEvent event) { + event.register(Registries.MATERIAL_CONDITION, helper -> + helper.register(CreateNuclear.asResource("biome_tag"), CODEC)); + } + + @Override + public KeyDispatchDataCodec codec() { + return KeyDispatchDataCodec.of(BiomeTagRule.CODEC); + } + + @Override + public SurfaceRules.Condition apply(SurfaceRules.Context context) { + return new Predicate(context); + } + + private class Predicate extends SurfaceRules.LazyYCondition { + protected Predicate(SurfaceRules.Context context) { + super(context); + } + + @Override + protected boolean compute() { + return this.context.biome.get().is(BiomeTagRule.this.tag); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/IrradiatedSurfaceRules.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/IrradiatedSurfaceRules.java new file mode 100644 index 0000000..04cfb27 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/IrradiatedSurfaceRules.java @@ -0,0 +1,75 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome.surfacerule; + +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.SurfaceRules.ConditionSource; +import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource; +import net.minecraft.world.level.levelgen.VerticalAnchor; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNBiomes; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNNoiseData; +import org.jetbrains.annotations.NotNull; + +public class IrradiatedSurfaceRules { + private static final ConditionSource IS_IRRADIATED_PLAIN = biome(CNBiomes.Irradiated.PLAIN); + + private static final RuleSource BEDROCK = block(Blocks.BEDROCK); + private static final RuleSource ENRICHED_SOUL_SOIL = block(CNBlocks.ENRICHED_SOUL_SOIL.get()); + private static final RuleSource LEAD_BLOCK = block(CNBlocks.LEAD_BLOCK.get()); + private static final RuleSource LEAD_ORE = block(CNBlocks.LEAD_ORE.get()); + private static final RuleSource RAW_LEAD_BLOCK = block(CNBlocks.RAW_LEAD_BLOCK.get()); + + private static final RuleSource IRRADIATED_PLAIN_MATERIAL = + SurfaceRules.ifTrue(IS_IRRADIATED_PLAIN, RAW_LEAD_BLOCK); + private static final RuleSource SURFACE_GENERATION = SurfaceRules.sequence( + SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, IRRADIATED_PLAIN_MATERIAL), + SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, IRRADIATED_PLAIN_MATERIAL) + ); + + public static final RuleSource DEFAULT_RULE = createDefaultRule(); + + public static @NotNull RuleSource createDefaultRule() { + return SurfaceRules.sequence( + SurfaceRules.ifTrue( + SurfaceRules.isBiome(CNBiomes.Irradiated.PLAIN), + SurfaceRules.sequence( + SurfaceRules.ifTrue( + SurfaceRules.noiseCondition(CNNoiseData.EROSION, 0.035, 0.0465), + LEAD_ORE + ), + SurfaceRules.ifTrue( + SurfaceRules.noiseCondition(CNNoiseData.EROSION, 0.039, 0.0545), + LEAD_BLOCK + ), + SurfaceRules.ifTrue( + SurfaceRules.noiseCondition(CNNoiseData.EROSION, 0.0545, 0.069), + RAW_LEAD_BLOCK + ) + ) + ), + + SurfaceRules.ifTrue(SurfaceRules.verticalGradient("bedrock_floor", VerticalAnchor.bottom(), VerticalAnchor.aboveBottom(5)), BEDROCK), + SurfaceRules.ifTrue(SurfaceRules.abovePreliminarySurface(), SURFACE_GENERATION), + SurfaceRules.ifTrue(SurfaceRules.verticalGradient("enriched", VerticalAnchor.absolute(-4), VerticalAnchor.absolute(4)), ENRICHED_SOUL_SOIL) + ); + } + + private static @NotNull RuleSource block(@NotNull Block block) { + return SurfaceRules.state(block.defaultBlockState()); + } + + public static @NotNull ConditionSource biome(@NotNull TagKey biome) { + return new BiomeTagRule(biome); + } + + @SafeVarargs + public static @NotNull ConditionSource biome(@NotNull ResourceKey @NotNull ... keys) { + return SurfaceRules.isBiome(keys); + } + +} \ No newline at end of file diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 79226f6..feb192a 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1,3 +1,12 @@ public net.minecraft.world.item.crafting.RecipeManager f_44007_ # recipes public net.minecraft.world.item.alchemy.PotionBrewing m_43513_(Lnet/minecraft/world/item/alchemy/Potion;Lnet/minecraft/world/item/Item;Lnet/minecraft/world/item/alchemy/Potion;)V + +public net.minecraft.world.level.levelgen.SurfaceRules$Context +public net.minecraft.world.level.levelgen.SurfaceRules$LazyYCondition +public net.minecraft.world.level.levelgen.SurfaceRules$Condition +public net.minecraft.world.level.levelgen.SurfaceRules$Context biome +public net.minecraft.world.level.levelgen.NoiseRouterData SHIFT_X +public net.minecraft.world.level.levelgen.NoiseRouterData Y +public net.minecraft.world.level.levelgen.NoiseRouterData SHIFT_Z +public net.minecraft.client.Camera move(DDD)V \ No newline at end of file diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml index dc88615..24693ba 100644 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -1,6 +1,6 @@ modLoader="javafml" #mandatory loaderVersion="${loader_version_range}" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. -issueTrackerURL="https://github.com/Giovanniricotta2002/CreateNuclearForge/issues" +issueTrackerURL="https://github.com/Create-Nuclear-Team/CreateNuclearNeoForge/issues" license="${mod_license}" @@ -10,7 +10,8 @@ version="${mod_version}" displayName="${mod_name}" authors="${mod_authors}" description='''${mod_description}''' -logoFile = "logo.png" +logoFile = "icon.png" + [[mixins]] config="createnuclear.neoforge.mixins.json" @@ -20,14 +21,16 @@ type="required" versionRange="${neo_version_range}" ordering="NONE" side="BOTH" -[[dependencies.${mod_id}]] + +[[dependencies."${mod_id}"]] modId="minecraft" mandatory=true # This version range declares a minimum of the current minecraft version up to but not including the next major version versionRange="${minecraft_version_range}" ordering="NONE" side="BOTH" -[[dependencies.${mod_id}]] + +[[dependencies."${mod_id}"]] modId="create" mandatory=true versionRange="${create_version_range}" diff --git a/src/main/resources/assets/createnuclear/lang/default/interface.json b/src/main/resources/assets/createnuclear/lang/default/interface.json index 1fc72ee..8b659cd 100644 --- a/src/main/resources/assets/createnuclear/lang/default/interface.json +++ b/src/main/resources/assets/createnuclear/lang/default/interface.json @@ -6,6 +6,10 @@ "emi.category.createnuclear.fan_enriched": "Bulk Enriching", "create.recipe.fan_enriched.fan": "Fan behind Enriched Fire", + "createnuclear.snow_powder.fan.recipe": "Cryogenic fan", + "emi.category.createnuclear.snow_powder": "Cryogenic fan", + "create.recipe.fan_snow_powder.fan": "Fan behind Powder Snow", + "gui.createnuclear.reactor_controller.title": "Reactor Controller", "gui.createnuclear.reactor_input.title": "Reactor Input Storage", @@ -17,9 +21,75 @@ "createnuclear.tooltip.heatLevel.danger": "Danger", "createnuclear.generic.unit.heat": "Q", - "createnuclear.tooltip.item.uranium.rod": "Uranium Rod: ", - "createnuclear.tooltip.item.graphene.rod": "Graphite Rod: ", + "createnuclear.tooltip.item.fuel.rod": "Fuel Rod: ", + "createnuclear.tooltip.item.cooled.rod": "Cooler Rod: ", "createnuclear.tooltip.item.unknown.rod": "Unknown: ", - "createnuclear.gui.reactor_controller.info_header.title": "Heat value" + "createnuclear.tooltip.item.empty.rod": "Input Items: ", + "createnuclear.gui.reactor_controller.info_header.title": "Heat value", + + "createnuclear.generic.unit.countCooled.rod": "Count Cooled Rod: %d", + "createnuclear.generic.unit.countFuel.rod": "Count Fuel Rod: %d", + "createnuclear.generic.unit.count.rod": "Counts %s Rod", + "createnuclear.display_source.reactor_count_rod": "Count Rod in Pattern", + "createnuclear.display_source.reactor_controller_count_rod.fuel": "Fuel", + "createnuclear.display_source.reactor_controller_count_rod.cooled": "Cooled", + + "createnuclear.generic.unit.heat.value": "Q", + "createnuclear.generic.unit.heat.rotation": "RPM", + "createnuclear.generic.unit.heat.type": "Heat Level: %s", + "createnuclear.generic.unit.fluid.value": "mB", + "createnuclear.display_source.heat.value": "Q", + "createnuclear.display_source.heat.rotation": "RPM", + "createnuclear.display_source.heat.type": "Heat level", + "createnuclear.display_source.reactor_summary": "Reactor Summary", + "createnuclear.display_source.heat": "Reactor Heat", + "createnuclear.display_source.liquid_level": "Reactor Liquid Level", + "createnuclear.display_source.fuel": "Reactor Fuel", + "createnuclear.display_source.cooler": "Reactor Cooler", + "createnuclear.display_source.size": "Reactor Size", + "createnuclear.display_source.reactor_summary.no_controller": "Reactor not found", + "createnuclear.display_source.reactor_summary.status": "Status:", + "createnuclear.display_source.reactor_summary.active": "ACTIVE", + "createnuclear.display_source.reactor_summary.idle": "IDLE", + "createnuclear.display_source.reactor_summary.temperature": "Temp:", + "createnuclear.display_source.reactor_summary.fuel": "Rods:", + "createnuclear.display_source.reactor_summary.coolant": "Coolant:", + "createnuclear.display_source.reactor.not_enough_space": "Not enough space ", + "createnuclear.display_source.reactor.for_reactor_status": "for reactor status", + "createnuclear.display_source.reactor.no_controller": "No Reactor Controller found", + "createnuclear.display_source.reactor.status": "Status: ", + "createnuclear.display_source.reactor.active": "ACTIVE", + "createnuclear.display_source.reactor.idle": "IDLE", + "createnuclear.display_source.reactor.size": "Tier: ", + "createnuclear.display_source.reactor.fuel": "Fuel: ", + "createnuclear.display_source.reactor.cooler": "Cooler: ", + "createnuclear.display_source.reactor.heat": "Heat: ", + "createnuclear.display_source.reactor.mode.value": "Values", + "createnuclear.display_source.reactor.mode.percent": "Percentages", + "createnuclear.display_source.reactor.mode.gauge": "Gauges", + "createnuclear.display_source.reactor.size.small": "Small", + "createnuclear.display_source.reactor.size.medium": "Medium", + "createnuclear.display_source.reactor.size.large": "Large", + "createnuclear.display_source.reactor.mode.normal": "Normal", + "createnuclear.display_source.reactor.fluid": "Fluid: ", + + "createnuclear.generic.unit.liquid": "WIP", + "createnuclear.display_source.liquid": "Liquid Level", + "createnuclear.tooltip.fluid": "Fluid: %s ", + "createnuclear.tooltip.fluid.none": "Fluid: None ", + "createnuclear.tooltip.fluid.amount": "%d mb", + + "createnuclear.generic.unit.seconds": "s", + "createnuclear.notification.reactor.meltdown_in": "CORE MELTDOWN IN ", + "createnuclear.notification.reactor.overheating": "WARNING: CORE OVERHEATING", + "createnuclear.notification.reactor.critical_failure": "CRITICAL FAILURE", + "createnuclear.notification.reactor.imminent_explosion": "IMMINENT EXPLOSION", + "createnuclear.notification.reactor.stabilized": "CORE STABILIZED", + "createnuclear.notification.reactor.destroyed": "REACTOR DESTROYED", + "createnuclear.notification.reactor.meltdown_finished": "Critical meltdown completed", + "createnuclear.notification.reactor.disassembled": "Reactor has been disassembled", + "createnuclear.notification.reactor.assembled": "Reactor has been assembled", + "death.attack.createnuclear.radiation": "%1$s died from radiation", + "death.attack.createnuclear.fan_radiation": "%1$s died from radiation blast" } diff --git a/src/main/resources/assets/createnuclear/lang/default/irradiated.json b/src/main/resources/assets/createnuclear/lang/default/irradiated.json new file mode 100644 index 0000000..fab98a1 --- /dev/null +++ b/src/main/resources/assets/createnuclear/lang/default/irradiated.json @@ -0,0 +1,3 @@ +{ + "irradiated.taming.wip": "This creature cannot be tamed yet - irradiated mobs are still a work in progress" +} diff --git a/src/main/resources/assets/createnuclear/lang/default/potion.json b/src/main/resources/assets/createnuclear/lang/default/potion.json index 9134804..af7439e 100644 --- a/src/main/resources/assets/createnuclear/lang/default/potion.json +++ b/src/main/resources/assets/createnuclear/lang/default/potion.json @@ -15,5 +15,17 @@ "item.minecraft.tipped_arrow.effect.potion_of_radiation_1": "Arrow of Radiation", "item.minecraft.tipped_arrow.effect.potion_of_radiation_augment_1": "Arrow of Radiation", - "item.minecraft.tipped_arrow.effect.potion_of_radiation_2": "Arrow of Radiation" + "item.minecraft.tipped_arrow.effect.potion_of_radiation_2": "Arrow of Radiation", + + "effect.createnuclear.iodine": "Iodine", + + "item.minecraft.potion.effect.potion_of_iodine": "Potion of Iodine", + "item.minecraft.splash_potion.effect.potion_of_iodine": "Splash Potion of Iodine", + "item.minecraft.lingering_potion.effect.potion_of_iodine": "Lingering Potion of Iodine", + "item.minecraft.tipped_arrow.effect.potion_of_iodine": "Arrow of Iodine", + + "item.minecraft.potion.effect.potion_of_iodine_augment": "Potion of Iodine", + "item.minecraft.splash_potion.effect.potion_of_iodine_augment": "Splash Potion of Iodine", + "item.minecraft.lingering_potion.effect.potion_of_iodine_augment": "Lingering Potion of Iodine", + "item.minecraft.tipped_arrow.effect.potion_of_iodine_augment": "Arrow of Iodine" } \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/lang/default/reactor.json b/src/main/resources/assets/createnuclear/lang/default/reactor.json index 67908b9..1ca9977 100644 --- a/src/main/resources/assets/createnuclear/lang/default/reactor.json +++ b/src/main/resources/assets/createnuclear/lang/default/reactor.json @@ -4,5 +4,14 @@ "reactor.info.assembled.creator": "Reactor has been assembled", "reactor.info.is": "controller is", "reactor.item.gui.name": "Config Pattern", - "reactor.update.casing.input": "Update the casing in input" + "reactor.update.casing.input": "Update the casing in input", + + "createnuclear.reactor.debug.title": "--- Reactor diagnostics ---", + "createnuclear.reactor.debug.summary": "%s: %s registered, %s valid", + "createnuclear.reactor.debug.registered_position": " registered @ %s", + "createnuclear.reactor.debug.valid_position": " valid @ %s", + "createnuclear.reactor.debug.label.input": "Input", + "createnuclear.reactor.debug.label.fluid_input": "Fluid Input", + "createnuclear.reactor.debug.label.output": "Output", + "createnuclear.reactor.debug.label.alarm": "Alarm" } \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/lang/default/tooltips.json b/src/main/resources/assets/createnuclear/lang/default/tooltips.json index 94b20cf..85fa69a 100644 --- a/src/main/resources/assets/createnuclear/lang/default/tooltips.json +++ b/src/main/resources/assets/createnuclear/lang/default/tooltips.json @@ -8,6 +8,10 @@ "block.createnuclear.reactor_input.tooltip.condition1": "When the Reactor is assembled", "block.createnuclear.reactor_input.tooltip.behaviour1": "Insert _uranium_ and _graphene_ rods in large quantities to power _the reactor_ ", + "block.createnuclear.reactor_fluid_input.tooltip.summary": "_The Reactor Fluid Input_ is a _block_ that can be used to insert _Water_ or _Liquid Nitrogen_ into the Reactor.", + "block.createnuclear.reactor_fluid_input.tooltip.condition1": "When the reactor is assembled", + "block.createnuclear.reactor_fluid_input.tooltip.behaviour1": "Insert _Water_ or _Liquid Nitrogen_ in large quantities to power _The Reactor_ and avoid _overheating_.", + "block.createnuclear.reactor_controller.tooltip.summary": " The _Reactor Controller_ is the _most important_ block for operating the reactor", "block.createnuclear.reactor_controller.tooltip.condition1": "When the reactor is assembled", @@ -34,14 +38,25 @@ "item.createnuclear.uranium_rod.tooltip.summary": "_Stick_ to be used in the _reactor input_ to operate it.", "item.createnuclear.reactor_blueprint_item.tooltip.summary": "It allows you to configure your own pattern.", - "item.createnuclear.reactor_blueprint_item.tooltip.condition1": "Filled with graphite and uranium rods", + "item.createnuclear.reactor_blueprint_item.tooltip.condition1": "Filled with cooling and fuel rods", "item.createnuclear.reactor_blueprint_item.tooltip.behaviour1": "_Right_ click to fill it.", "item.createnuclear.reactor_blueprint_item.tooltip.condition2": "The reactor must be assembled", "item.createnuclear.reactor_blueprint_item.tooltip.behaviour2": "_Right_ click on the reactor controller to open it.", + "item.createnuclear.reactor_blueprint.tooltip": "Used to design and visualize the reactor's interior layout.", + "item.createnuclear.reactor_blueprint.tooltip_hint": "§7Press §eShift + Right Click §7to with the blueprint in hand to get the Wiki link.", + "item.createnuclear.reactor_blueprint.chat_info": "Follow the link to open the documentation:", + "item.createnuclear.reactor_blueprint.wiki_link": "[Open Official Wiki]", "block.createnuclear.enriched_soul_soil.tooltip.summary": "The _only_ block who create _enriched fire_.Can be used to _craft_ enriched campfire or just to make a _green fire_.", + "createnuclear.tooltip.statRod": "Rod Stat Pattern:", + "createnuclear.tooltip.baseRodHeat": "Base Rod Heat: %d Q", + "createnuclear.tooltip.proximityRodHeat": "Proximity Rod Heat: %.2f Q", + "createnuclear.tooltip.rodTimer": "Rod Duration: %d tick", + "createnuclear.tooltip.ratio": "Rod Value for ratio: %d", + "createnuclear.tooltip.typeRod": "Rod Type: %s", + "createnuclear.tooltip.cloth.color": "Color of armor piece: %s", "tag.item.c.coal_dusts": "Coal Dusts", @@ -59,5 +74,7 @@ "tag.item.trinkets.head.face": "Head Face", - "overlay.event_message": "⚠ Warning ⚠ %s timer" + "overlay.event_message": "⚠ Warning ⚠ %s timer", + + "attribute.name.createnuclear.generic.irradiated_resistance": "Radiation Resistance" } \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/lang/en_US.json b/src/main/resources/assets/createnuclear/lang/en_US.json index f7cde70..1cce5e8 100644 --- a/src/main/resources/assets/createnuclear/lang/en_US.json +++ b/src/main/resources/assets/createnuclear/lang/en_US.json @@ -23,19 +23,17 @@ "createnuclear.enriched.fan.recipe": "Bulk Enriched", "createnuclear.generic.unit.heat": "Q", "createnuclear.gui.reactor_controller.info_header.title": "Heat value", - "createnuclear.ponder.reactor.header": "Setup from Reactor", - "createnuclear.ponder.reactor.text_1": "Floor 1", - "createnuclear.ponder.reactor.text_10": "Floor 7", - "createnuclear.ponder.reactor.text_2": "Reactor Output: This is where the block outputs the energy (SU) generated from production.", - "createnuclear.ponder.reactor.text_3": "Floor 2", - "createnuclear.ponder.reactor.text_4": "Floor 3", - "createnuclear.ponder.reactor.text_5": "Floor 4", - "createnuclear.ponder.reactor.text_6": "Reactor Input: A block that stores uranium rods and graphite rods to operate the reactor.", - "createnuclear.ponder.reactor.text_7": "Reactor Controller: The most important block for operating the reactor; it handles all the calculations needed to generate energy.", - "createnuclear.ponder.reactor.text_8": "Floor 5", - "createnuclear.ponder.reactor.text_9": "Floor 6", - "createnuclear.ponder.reactor_blueprint.header": "Enable controller", - "createnuclear.ponder.reactor_blueprint.text_1": "Reactor Blueprint: The most important item; it allows you to configure the reactor according to specific patterns.", + "createnuclear.ponder.reactor.title.t1": "Reactor T1 — Construction", + "createnuclear.ponder.reactor.title.t2": "Reactor T2 — Construction", + "createnuclear.ponder.reactor.title.t3": "Reactor T3 — Construction", + "createnuclear.ponder.reactor.floor": "Floor ", + "createnuclear.ponder.reactor.input1": "Input: stores uranium/graphite. One per rod.", + "createnuclear.ponder.reactor.input2": "Input 2: secondary input (place on an edge, not on the frame).", + "createnuclear.ponder.reactor.liquid_input": "Liquid input: cooling fluid inlet. Place on an edge.", + "createnuclear.ponder.reactor.alarm": "Alarm: place on an edge (not on the frame). Triggers on overheating.", + "createnuclear.ponder.reactor.output": "Output: produces energy (SU).", + "createnuclear.ponder.reactor.controller": "Controller: central block that manages the reactor.", + "createnuclear.ponder.reactor.use_blueprint": "Use the Reactor Blueprint to assemble the multiblock.", "createnuclear.tooltip.heatLevel": "Heat Level", "createnuclear.tooltip.heatLevel.caution": "Caution", "createnuclear.tooltip.heatLevel.danger": "Danger", @@ -45,6 +43,7 @@ "createnuclear.tooltip.item.graphene.rod": "Graphene Rod: ", "createnuclear.tooltip.item.unknown.rod": "Unknown: ", "createnuclear.tooltip.item.uranium.rod": "Uranium Rod: ", + "effect.createnuclear.iodine": "Iodine", "effect.createnuclear.radiation": "Radiation", "emi.category.createnuclear.fan_enriched": "Bulk Enriched", "entity.createnuclear.irradiated_cat": "Irradiated Cat", @@ -133,15 +132,23 @@ "item.createnuclear.yellow_anti_radiation_leggings": "Yellow Anti Radiation Leggings", "item.createnuclear.yellow_cloth": "Yellow Cloth", "item.createnuclear.yellowcake": "Yellowcake", + "item.minecraft.lingering_potion.effect.potion_of_iodine": "Lingering Potion of Iodine", + "item.minecraft.lingering_potion.effect.potion_of_iodine_augment": "Lingering Potion of Iodine", "item.minecraft.lingering_potion.effect.potion_of_radiation_1": "Lingering Potion of Radiation", "item.minecraft.lingering_potion.effect.potion_of_radiation_2": "Lingering Potion of Radiation", "item.minecraft.lingering_potion.effect.potion_of_radiation_augment_1": "Lingering Potion of Radiation", + "item.minecraft.potion.effect.potion_of_iodine": "Potion of Iodine", + "item.minecraft.potion.effect.potion_of_iodine_augment": "Potion of Iodine", "item.minecraft.potion.effect.potion_of_radiation_1": "Potion of Radiation", "item.minecraft.potion.effect.potion_of_radiation_2": "Potion of Radiation", "item.minecraft.potion.effect.potion_of_radiation_augment_1": "Potion of Radiation", + "item.minecraft.splash_potion.effect.potion_of_iodine": "Splash Potion of Iodine", + "item.minecraft.splash_potion.effect.potion_of_iodine_augment": "Splash Potion of Iodine", "item.minecraft.splash_potion.effect.potion_of_radiation_1": "Splash Potion of Radiation", "item.minecraft.splash_potion.effect.potion_of_radiation_2": "Splash Potion of Radiation", "item.minecraft.splash_potion.effect.potion_of_radiation_augment_1": "Splash Potion of Radiation", + "item.minecraft.tipped_arrow.effect.potion_of_iodine": "Arrow of Iodine", + "item.minecraft.tipped_arrow.effect.potion_of_iodine_augment": "Arrow of Iodine", "item.minecraft.tipped_arrow.effect.potion_of_radiation_1": "Arrow of Radiation", "item.minecraft.tipped_arrow.effect.potion_of_radiation_2": "Arrow of Radiation", "item.minecraft.tipped_arrow.effect.potion_of_radiation_augment_1": "Arrow of Radiation", @@ -165,5 +172,6 @@ "tag.item.createnuclear.fuel": "Fuel", "tag.item.minecraft.all.campfires": "All Campfires", "tag.item.minecraft.campfires": "Campfires", - "tag.item.trinkets.head.face": "Head Face" + "tag.item.trinkets.head.face": "Head Face", + "item.createnuclear.raw_thorium": "Raw Thorium" } \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/lang/fr_fr.json b/src/main/resources/assets/createnuclear/lang/fr_fr.json index 702c09e..d6ee210 100644 --- a/src/main/resources/assets/createnuclear/lang/fr_fr.json +++ b/src/main/resources/assets/createnuclear/lang/fr_fr.json @@ -136,6 +136,7 @@ "createnuclear.tooltip.item.graphene.rod": "Barre de graphite : ", "createnuclear.tooltip.item.unknown.rod": "Inconnue : ", "createnuclear.tooltip.item.uranium.rod": "Barre d'uranium : ", + "effect.createnuclear.iodine": "Iode", "effect.createnuclear.radiation": "Radiation", "emi.category.createnuclear.fan_enriched": "Enrichi en bloc", "entity.createnuclear.irradiated_cat": "Chat irradié", @@ -234,15 +235,23 @@ "item.createnuclear.yellow_anti_radiation_leggings": "Jambières anti-radiations jaune", "item.createnuclear.yellow_cloth": "Tissu jaune", "item.createnuclear.yellowcake": "Yellowcake", + "item.minecraft.lingering_potion.effect.potion_of_iodine": "Potion d'iode persistante", + "item.minecraft.lingering_potion.effect.potion_of_iodine_augment": "Potion d'iode persistante", "item.minecraft.lingering_potion.effect.potion_of_radiation_1": "Potion de radiation persistante", "item.minecraft.lingering_potion.effect.potion_of_radiation_2": "Potion de radiation persistante", "item.minecraft.lingering_potion.effect.potion_of_radiation_augment_1": "Potion de radiation persistante", + "item.minecraft.potion.effect.potion_of_iodine": "Potion d'iode", + "item.minecraft.potion.effect.potion_of_iodine_augment": "Potion d'iode", "item.minecraft.potion.effect.potion_of_radiation_1": "Potion de radiation", "item.minecraft.potion.effect.potion_of_radiation_2": "Potion de radiation", "item.minecraft.potion.effect.potion_of_radiation_augment_1": "Potion de radiation", + "item.minecraft.splash_potion.effect.potion_of_iodine": "Potion d'iode jetable", + "item.minecraft.splash_potion.effect.potion_of_iodine_augment": "Potion d'iode jetable", "item.minecraft.splash_potion.effect.potion_of_radiation_1": "Potion de radiation jetable", "item.minecraft.splash_potion.effect.potion_of_radiation_2": "Potion de radiation jetable", "item.minecraft.splash_potion.effect.potion_of_radiation_augment_1": "Potion de radiation jetable", + "item.minecraft.tipped_arrow.effect.potion_of_iodine": "Flèche d'iode", + "item.minecraft.tipped_arrow.effect.potion_of_iodine_augment": "Flèche d'iode", "item.minecraft.tipped_arrow.effect.potion_of_radiation_1": "Flèche irradiée", "item.minecraft.tipped_arrow.effect.potion_of_radiation_2": "Flèche irradiée", "item.minecraft.tipped_arrow.effect.potion_of_radiation_augment_1": "Flèche irradiée", @@ -267,5 +276,6 @@ "tag.item.createnuclear.fuel": "Carburant", "tag.item.minecraft.all.campfires": "Tous les feux de camps", "tag.item.minecraft.campfires": "Feu de camps", - "tag.item.trinkets.head.face": "Face avant" + "tag.item.trinkets.head.face": "Face avant", + "item.createnuclear.raw_thorium": "Thorium brut" } \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/block/enriching/campfire/block.json b/src/main/resources/assets/createnuclear/models/block/enriching/campfire/block.json index 90260a8..95840f6 100644 --- a/src/main/resources/assets/createnuclear/models/block/enriching/campfire/block.json +++ b/src/main/resources/assets/createnuclear/models/block/enriching/campfire/block.json @@ -1,4 +1,5 @@ { + "render_type": "cutout_mipped", "parent": "minecraft:block/template_campfire", "textures": { "fire": "createnuclear:block/enriching/campfire/enriching_flame", diff --git a/src/main/resources/assets/createnuclear/models/block/enriching/campfire/block_off.json b/src/main/resources/assets/createnuclear/models/block/enriching/campfire/block_off.json index 9dc5476..7bfa232 100644 --- a/src/main/resources/assets/createnuclear/models/block/enriching/campfire/block_off.json +++ b/src/main/resources/assets/createnuclear/models/block/enriching/campfire/block_off.json @@ -1,4 +1,5 @@ { + "render_type": "cutout_mipped", "parent": "block/block", "display": { "head": { diff --git a/src/main/resources/assets/createnuclear/models/block/enriching/fire/floor0.json b/src/main/resources/assets/createnuclear/models/block/enriching/fire/floor0.json index ba4f1de..759a647 100644 --- a/src/main/resources/assets/createnuclear/models/block/enriching/fire/floor0.json +++ b/src/main/resources/assets/createnuclear/models/block/enriching/fire/floor0.json @@ -1,4 +1,5 @@ { + "render_type": "cutout", "parent": "minecraft:block/template_fire_floor", "textures": { "fire": "createnuclear:block/enriching/fire/fire_0" diff --git a/src/main/resources/assets/createnuclear/models/block/enriching/fire/floor1.json b/src/main/resources/assets/createnuclear/models/block/enriching/fire/floor1.json index d90aa55..deaa294 100644 --- a/src/main/resources/assets/createnuclear/models/block/enriching/fire/floor1.json +++ b/src/main/resources/assets/createnuclear/models/block/enriching/fire/floor1.json @@ -1,4 +1,5 @@ { + "render_type": "cutout", "parent": "minecraft:block/template_fire_floor", "textures": { "fire": "createnuclear:block/enriching/fire/fire_1" diff --git a/src/main/resources/assets/createnuclear/models/block/enriching/fire/side0.json b/src/main/resources/assets/createnuclear/models/block/enriching/fire/side0.json index 7ae3dde..e3de87b 100644 --- a/src/main/resources/assets/createnuclear/models/block/enriching/fire/side0.json +++ b/src/main/resources/assets/createnuclear/models/block/enriching/fire/side0.json @@ -1,4 +1,5 @@ { + "render_type": "cutout", "parent": "minecraft:block/template_fire_side", "textures": { "fire": "createnuclear:block/enriching/fire/fire_0" diff --git a/src/main/resources/assets/createnuclear/models/block/enriching/fire/side1.json b/src/main/resources/assets/createnuclear/models/block/enriching/fire/side1.json index 1647b6a..bdf798c 100644 --- a/src/main/resources/assets/createnuclear/models/block/enriching/fire/side1.json +++ b/src/main/resources/assets/createnuclear/models/block/enriching/fire/side1.json @@ -1,4 +1,5 @@ { + "render_type": "cutout", "parent": "minecraft:block/template_fire_side", "textures": { "fire": "createnuclear:block/enriching/fire/fire_1" diff --git a/src/main/resources/assets/createnuclear/models/block/enriching/fire/side_alt0.json b/src/main/resources/assets/createnuclear/models/block/enriching/fire/side_alt0.json index 98617cf..c89c60a 100644 --- a/src/main/resources/assets/createnuclear/models/block/enriching/fire/side_alt0.json +++ b/src/main/resources/assets/createnuclear/models/block/enriching/fire/side_alt0.json @@ -1,4 +1,5 @@ { + "render_type": "cutout", "parent": "minecraft:block/template_fire_side_alt", "textures": { "fire": "createnuclear:block/enriching/fire/fire_0" diff --git a/src/main/resources/assets/createnuclear/models/block/enriching/fire/side_alt1.json b/src/main/resources/assets/createnuclear/models/block/enriching/fire/side_alt1.json index 045ff8d..5c57dae 100644 --- a/src/main/resources/assets/createnuclear/models/block/enriching/fire/side_alt1.json +++ b/src/main/resources/assets/createnuclear/models/block/enriching/fire/side_alt1.json @@ -1,4 +1,5 @@ { + "render_type": "cutout", "parent": "minecraft:block/template_fire_side_alt", "textures": { "fire": "createnuclear:block/enriching/fire/fire_1" diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/alarm/block.json b/src/main/resources/assets/createnuclear/models/block/reactor/alarm/block.json new file mode 100644 index 0000000..0db3279 --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/block/reactor/alarm/block.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/controller/item.json b/src/main/resources/assets/createnuclear/models/block/reactor/controller/item.json index 7a0ca23..fa132ac 100644 --- a/src/main/resources/assets/createnuclear/models/block/reactor/controller/item.json +++ b/src/main/resources/assets/createnuclear/models/block/reactor/controller/item.json @@ -2,9 +2,9 @@ "credit": "Made with Blockbench", "parent": "block/cube", "textures": { - "1": "createnuclear:block/reactor/controller/controller_panel", + "1": "createnuclear:block/reactor/controller/controller_panel_on", "2": "createnuclear:block/reactor/casing/reactor_casing", - "particle": "createnuclear:block/reactor/controller/controller_panel" + "particle": "createnuclear:block/reactor/controller/controller_panel_on" }, "elements": [ { diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/fluid_input/fluid_input.json b/src/main/resources/assets/createnuclear/models/block/reactor/fluid_input/fluid_input.json new file mode 100644 index 0000000..92c6a85 --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/block/reactor/fluid_input/fluid_input.json @@ -0,0 +1,92 @@ +{ + "render_type": "cutout_mipped", + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "createnuclear:block/reactor/casing/reactor_casing", + "1": "createnuclear:block/reactor/fluid_input/input", + "2": "createnuclear:block/reactor/casing/reactor_casing", + "particle": "createnuclear:block/reactor/casing/reactor_casing" + }, + "elements": [ + { + "name": "right", + "from": [14, 0, 15], + "to": [16, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, + "faces": { + "east": {"uv": [0, 0, 1, 16], "texture": "#0"}, + "south": {"uv": [14, 0, 16, 16], "texture": "#1"}, + "west": {"uv": [13, 0, 14, 16], "texture": "#1"}, + "up": {"uv": [14, 0, 16, 1], "rotation": 180, "texture": "#2"}, + "down": {"uv": [14, 15, 16, 16], "rotation": 180, "texture": "#2"} + } + }, + { + "name": "left", + "from": [0, 0, 15], + "to": [2, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, + "faces": { + "north": {"uv": [0, 0, 2, 16], "texture": "#1"}, + "east": {"uv": [2, 0, 3, 16], "texture": "#1"}, + "south": {"uv": [0, 0, 2, 16], "texture": "#1"}, + "west": {"uv": [15, 0, 16, 16], "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "rotation": 180, "texture": "#2"}, + "down": {"uv": [0, 15, 2, 16], "rotation": 180, "texture": "#2"} + } + }, + { + "name": "down", + "from": [2, 0, 15], + "to": [14, 2, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, + "faces": { + "south": {"uv": [2, 14, 14, 16], "texture": "#1"}, + "up": {"uv": [2, 14, 14, 15], "rotation": 180, "texture": "#1"}, + "down": {"uv": [2, 15, 14, 16], "rotation": 180, "texture": "#2"} + } + }, + { + "name": "up", + "from": [2, 14, 15], + "to": [14, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, + "faces": { + "south": {"uv": [2, 0, 14, 2], "texture": "#1"}, + "up": {"uv": [2, 0, 14, 1], "rotation": 180, "texture": "#2"}, + "down": {"uv": [2, 1, 14, 2], "rotation": 180, "texture": "#1"} + } + }, + { + "name": "core", + "from": [0, 0, 0], + "to": [16, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#0"}, + "east": {"uv": [1, 0, 16, 16], "texture": "#0"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "west": {"uv": [0, 0, 15, 16], "texture": "#0"}, + "up": {"uv": [0, 1, 16, 16], "rotation": 180, "texture": "#2"}, + "down": {"uv": [0, 0, 16, 15], "rotation": 180, "texture": "#2"} + } + } + ], + "groups": [ + { + "name": "block", + "origin": [8, 8, 8], + "color": 0, + "children": [ + { + "name": "north", + "origin": [8, 8, 8], + "color": 0, + "children": [0, 1, 2, 3] + }, + 4 + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/fluid_input/fluid_input_vertical.json b/src/main/resources/assets/createnuclear/models/block/reactor/fluid_input/fluid_input_vertical.json new file mode 100644 index 0000000..e232335 --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/block/reactor/fluid_input/fluid_input_vertical.json @@ -0,0 +1,250 @@ +{ + "render_type": "cutout_mipped", + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "createnuclear:block/reactor/fluid_input/input", + "1": "createnuclear:block/reactor/casing/reactor_casing", + "2": "createnuclear:block/reactor/casing/reactor_casing", + "particle": "createnuclear:block/reactor/fluid_input/input" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 14, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [2, 0, 16, 16], "rotation": 90, "texture": "#1"}, + "east": {"uv": [0, 0, 14, 16], "rotation": 270, "texture": "#2"}, + "south": {"uv": [2, 0, 16, 16], "rotation": 90, "texture": "#1"}, + "west": {"uv": [2, 0, 16, 16], "rotation": 90, "texture": "#2"}, + "up": {"uv": [0, 0, 16, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#2"} + } + }, + { + "from": [12, 14, 0], + "to": [16, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 12, 2, 16], "rotation": 90, "texture": "#1"}, + "east": {"uv": [14, 0, 16, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 4], "rotation": 90, "texture": "#1"}, + "west": {"uv": [3, 0, 5, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [0, 0, 4, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [12, 0, 16, 16], "texture": "#0"} + } + }, + { + "from": [0, 14, 0], + "to": [4, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 0, 2, 4], "rotation": 90, "texture": "#1"}, + "east": {"uv": [11, 0, 13, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 12, 2, 16], "rotation": 90, "texture": "#1"}, + "west": {"uv": [0, 0, 2, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [12, 0, 16, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 0, 4, 16], "texture": "#0"} + } + }, + { + "from": [4, 14, 0], + "to": [5, 16, 7], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 4, 2, 5], "rotation": 90, "texture": "#1"}, + "east": {"uv": [10, 9, 12, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [4, 9, 6, 10], "rotation": 90, "texture": "#0"}, + "west": {"uv": [10, 9, 12, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [11, 9, 12, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [11, 9, 12, 16], "texture": "#0"} + } + }, + { + "from": [11, 14, 0], + "to": [12, 16, 7], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 11, 2, 12], "rotation": 90, "texture": "#1"}, + "east": {"uv": [4, 9, 6, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [4, 9, 6, 10], "rotation": 90, "texture": "#0"}, + "west": {"uv": [4, 9, 6, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [4, 9, 5, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [4, 9, 5, 16], "texture": "#0"} + } + }, + { + "from": [11, 14, 9], + "to": [12, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [4, 6, 6, 7], "rotation": 90, "texture": "#0"}, + "east": {"uv": [4, 0, 6, 7], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 11, 2, 12], "rotation": 90, "texture": "#1"}, + "west": {"uv": [4, 0, 6, 7], "rotation": 90, "texture": "#0"}, + "up": {"uv": [4, 0, 5, 7], "rotation": 180, "texture": "#0"}, + "down": {"uv": [4, 0, 5, 7], "texture": "#0"} + } + }, + { + "from": [4, 14, 9], + "to": [5, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [4, 6, 6, 7], "rotation": 90, "texture": "#0"}, + "east": {"uv": [10, 0, 12, 7], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 4, 2, 5], "rotation": 90, "texture": "#1"}, + "west": {"uv": [10, 0, 12, 7], "rotation": 90, "texture": "#0"}, + "up": {"uv": [11, 0, 12, 7], "rotation": 180, "texture": "#0"}, + "down": {"uv": [11, 0, 12, 7], "texture": "#0"} + } + }, + { + "from": [5, 14, 10], + "to": [6, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [5, 5, 7, 6], "rotation": 90, "texture": "#0"}, + "east": {"uv": [9, 0, 11, 6], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 6, 2, 7], "rotation": 90, "texture": "#1"}, + "west": {"uv": [9, 0, 11, 6], "rotation": 90, "texture": "#0"}, + "up": {"uv": [10, 0, 11, 6], "rotation": 180, "texture": "#0"}, + "down": {"uv": [10, 0, 11, 6], "texture": "#0"} + } + }, + { + "from": [10, 14, 10], + "to": [11, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [5, 5, 7, 6], "rotation": 90, "texture": "#0"}, + "east": {"uv": [5, 0, 7, 6], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 10, 2, 11], "rotation": 90, "texture": "#1"}, + "west": {"uv": [5, 0, 7, 6], "rotation": 90, "texture": "#0"}, + "up": {"uv": [5, 0, 6, 6], "rotation": 180, "texture": "#0"}, + "down": {"uv": [5, 0, 6, 6], "texture": "#0"} + } + }, + { + "from": [10, 14, 0], + "to": [11, 16, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 10, 2, 11], "rotation": 90, "texture": "#1"}, + "east": {"uv": [5, 10, 7, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [5, 10, 7, 11], "rotation": 90, "texture": "#0"}, + "west": {"uv": [5, 10, 7, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [5, 10, 6, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [5, 10, 6, 16], "texture": "#0"} + } + }, + { + "from": [9, 14, 0], + "to": [10, 16, 5], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 9, 2, 10], "rotation": 90, "texture": "#1"}, + "east": {"uv": [6, 11, 8, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [6, 11, 8, 12], "rotation": 90, "texture": "#0"}, + "west": {"uv": [6, 11, 8, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [6, 11, 7, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [6, 11, 7, 16], "texture": "#0"} + } + }, + { + "from": [6, 14, 0], + "to": [7, 16, 5], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 6, 2, 7], "rotation": 90, "texture": "#1"}, + "east": {"uv": [8, 11, 10, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [6, 11, 8, 12], "rotation": 90, "texture": "#0"}, + "west": {"uv": [8, 11, 10, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [9, 11, 10, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9, 11, 10, 16], "texture": "#0"} + } + }, + { + "from": [6, 14, 11], + "to": [7, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [6, 4, 8, 5], "rotation": 90, "texture": "#0"}, + "east": {"uv": [8, 0, 10, 5], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 7, 2, 8], "rotation": 90, "texture": "#1"}, + "west": {"uv": [8, 0, 10, 5], "rotation": 90, "texture": "#0"}, + "up": {"uv": [9, 0, 10, 5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9, 0, 10, 5], "texture": "#0"} + } + }, + { + "from": [9, 14, 11], + "to": [10, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [6, 4, 8, 5], "rotation": 90, "texture": "#0"}, + "east": {"uv": [6, 0, 8, 5], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 9, 2, 10], "rotation": 90, "texture": "#1"}, + "west": {"uv": [6, 0, 8, 5], "rotation": 90, "texture": "#0"}, + "up": {"uv": [6, 0, 7, 5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [6, 0, 7, 5], "texture": "#0"} + } + }, + { + "from": [7, 14, 12], + "to": [9, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [3, 7, 5, 9], "rotation": 90, "texture": "#0"}, + "east": {"uv": [7, 0, 9, 4], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 7, 2, 9], "rotation": 90, "texture": "#1"}, + "west": {"uv": [7, 0, 9, 4], "rotation": 90, "texture": "#0"}, + "up": {"uv": [7, 0, 9, 4], "rotation": 180, "texture": "#0"}, + "down": {"uv": [7, 0, 9, 4], "texture": "#0"} + } + }, + { + "from": [7, 14, 0], + "to": [9, 16, 4], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 7, 2, 9], "rotation": 90, "texture": "#1"}, + "east": {"uv": [7, 12, 9, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [3, 7, 5, 9], "rotation": 90, "texture": "#0"}, + "west": {"uv": [7, 12, 9, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [7, 12, 9, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [7, 12, 9, 16], "texture": "#0"} + } + }, + { + "from": [5, 14, 0], + "to": [6, 16, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 5, 2, 6], "rotation": 90, "texture": "#1"}, + "east": {"uv": [9, 10, 11, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [5, 10, 7, 11], "rotation": 90, "texture": "#0"}, + "west": {"uv": [9, 10, 11, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [10, 10, 11, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [10, 10, 11, 16], "texture": "#0"} + } + } + ], + "groups": [ + { + "name": "group", + "origin": [0, 0, 0], + "color": 0, + "children": [ + 0, + { + "name": "face", + "origin": [8, 8, 8], + "color": 0, + "children": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/fluid_input/item.json b/src/main/resources/assets/createnuclear/models/block/reactor/fluid_input/item.json new file mode 100644 index 0000000..ddb1e1b --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/block/reactor/fluid_input/item.json @@ -0,0 +1,92 @@ +{ + "render_type": "cutout_mipped", + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "createnuclear:block/reactor/casing/reactor_casing", + "1": "createnuclear:block/reactor/fluid_input/input", + "2": "createnuclear:block/reactor/casing/reactor_casing", + "particle": "createnuclear:block/reactor/casing/reactor_casing" + }, + "elements": [ + { + "name": "right", + "from": [0, 0, 0], + "to": [2, 16, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, + "faces": { + "north": {"uv": [14, 0, 16, 16], "texture": "#1"}, + "east": {"uv": [13, 0, 14, 16], "texture": "#1"}, + "west": {"uv": [0, 0, 1, 16], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 1], "texture": "#2"}, + "down": {"uv": [14, 15, 16, 16], "texture": "#2"} + } + }, + { + "name": "left", + "from": [14, 0, 0], + "to": [16, 16, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, + "faces": { + "north": {"uv": [0, 0, 2, 16], "texture": "#1"}, + "east": {"uv": [15, 0, 16, 16], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 16], "texture": "#1"}, + "west": {"uv": [2, 0, 3, 16], "texture": "#1"}, + "up": {"uv": [0, 0, 2, 1], "texture": "#2"}, + "down": {"uv": [0, 15, 2, 16], "texture": "#2"} + } + }, + { + "name": "down", + "from": [2, 0, 0], + "to": [14, 2, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, + "faces": { + "north": {"uv": [2, 14, 14, 16], "texture": "#1"}, + "up": {"uv": [2, 14, 14, 15], "texture": "#1"}, + "down": {"uv": [2, 15, 14, 16], "texture": "#2"} + } + }, + { + "name": "up", + "from": [2, 14, 0], + "to": [14, 16, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, + "faces": { + "north": {"uv": [2, 0, 14, 2], "texture": "#1"}, + "up": {"uv": [2, 0, 14, 1], "texture": "#2"}, + "down": {"uv": [2, 1, 14, 2], "texture": "#1"} + } + }, + { + "name": "core", + "from": [0, 0, 1], + "to": [16, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "east": {"uv": [0, 0, 15, 16], "texture": "#0"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#0"}, + "west": {"uv": [1, 0, 16, 16], "texture": "#0"}, + "up": {"uv": [0, 1, 16, 16], "texture": "#2"}, + "down": {"uv": [0, 0, 16, 15], "texture": "#2"} + } + } + ], + "groups": [ + { + "name": "block", + "origin": [8, 8, 8], + "color": 0, + "children": [ + { + "name": "north", + "origin": [8, 8, 8], + "color": 0, + "children": [0, 1, 2, 3] + }, + 4 + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_bottom.json b/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_bottom.json index e315bae..d2d868c 100644 --- a/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_bottom.json +++ b/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_bottom.json @@ -1,25 +1,23 @@ { + "render_type": "cutout_mipped", + "format_version": "1.21.11", "credit": "Made with Blockbench", "parent": "block/block", "textures": { - "0": "createnuclear:block/reactor/casing/casing_inner", - "1": "createnuclear:block/reactor/casing/casing_top", "2": "createnuclear:block/reactor/frame/window", "3": "createnuclear:block/reactor/casing/reactor_casing", - "4": "createnuclear:fluid/uranium_still", - "5": "createnuclear:fluid/uranium_flow", - "particle": "createnuclear:block/reactor/casing/casing_inner" + "particle": "createnuclear:block/reactor/casing/reactor_casing" }, "elements": [ { "name": "SideRight", "from": [1, 4, 0], "to": [4, 16, 1], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, -23]}, + "rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 0.5]}, "faces": { "north": {"uv": [12, 5, 15, 12], "texture": "#3", "cullface": "north"}, "east": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "north"}, - "south": {"uv": [1, 0, 4, 12], "texture": "#3", "cullface": "north"}, + "south": {"uv": [1, 3, 4, 15], "texture": "#3", "cullface": "north"}, "west": {"uv": [4, 0, 5, 12], "texture": "#3"}, "down": {"uv": [1, 12, 4, 11], "texture": "#3"} } @@ -28,11 +26,11 @@ "name": "SideLeft", "from": [12, 4, 0], "to": [15, 16, 1], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, -23]}, + "rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 0.5]}, "faces": { "north": {"uv": [1, 5, 4, 12], "texture": "#3", "cullface": "north"}, "east": {"uv": [11, 0, 12, 12], "texture": "#3"}, - "south": {"uv": [12, 0, 15, 12], "texture": "#3", "cullface": "north"}, + "south": {"uv": [12, 3, 15, 15], "texture": "#3", "cullface": "north"}, "west": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "north"}, "down": {"uv": [12, 11, 15, 12], "texture": "#3"} } @@ -52,10 +50,11 @@ "name": "SideRight", "from": [15, 4, 1], "to": [16, 16, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [15.5, 10, 8]}, "faces": { "east": {"uv": [12, 5, 15, 12], "texture": "#3", "cullface": "east"}, "south": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "east"}, - "west": {"uv": [1, 0, 4, 12], "texture": "#3", "cullface": "east"}, + "west": {"uv": [1, 3, 4, 15], "texture": "#3", "cullface": "east"}, "down": {"uv": [11, 2, 12, 5], "texture": "#3"} } }, @@ -63,10 +62,11 @@ "name": "SideLeft", "from": [15, 4, 12], "to": [16, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [15.5, 10, 8]}, "faces": { "north": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "east"}, "east": {"uv": [1, 5, 4, 12], "texture": "#3", "cullface": "east"}, - "west": {"uv": [12, 0, 15, 12], "texture": "#3", "cullface": "east"}, + "west": {"uv": [12, 3, 15, 15], "texture": "#3", "cullface": "east"}, "down": {"uv": [12, 9, 13, 12], "texture": "#3"} } }, @@ -83,8 +83,9 @@ "name": "SideRight", "from": [12, 4, 15], "to": [15, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 15.5]}, "faces": { - "north": {"uv": [1, 0, 4, 12], "texture": "#3", "cullface": "south"}, + "north": {"uv": [1, 3, 4, 15], "texture": "#3", "cullface": "south"}, "south": {"uv": [12, 5, 15, 12], "texture": "#3", "cullface": "south"}, "west": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "south"}, "down": {"uv": [12, 11, 15, 12], "texture": "#3"} @@ -94,8 +95,9 @@ "name": "SideLeft", "from": [1, 4, 15], "to": [4, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 10, 15.5]}, "faces": { - "north": {"uv": [12, 0, 15, 12], "texture": "#3", "cullface": "south"}, + "north": {"uv": [12, 3, 15, 15], "texture": "#3", "cullface": "south"}, "east": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "south"}, "south": {"uv": [1, 5, 4, 12], "texture": "#3", "cullface": "south"}, "down": {"uv": [1, 11, 4, 12], "texture": "#3"} @@ -114,9 +116,10 @@ "name": "SideRight", "from": [0, 4, 12], "to": [1, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [0.5, 10, 8]}, "faces": { "north": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "west"}, - "east": {"uv": [1, 0, 4, 12], "texture": "#3", "cullface": "west"}, + "east": {"uv": [1, 3, 4, 15], "texture": "#3", "cullface": "west"}, "west": {"uv": [12, 5, 15, 12], "texture": "#3", "cullface": "west"}, "down": {"uv": [11, 9, 12, 12], "texture": "#3"} } @@ -125,8 +128,9 @@ "name": "SideLeft", "from": [0, 4, 1], "to": [1, 16, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [0.5, 10, 8]}, "faces": { - "east": {"uv": [12, 0, 15, 12], "texture": "#3", "cullface": "west"}, + "east": {"uv": [12, 3, 15, 15], "texture": "#3", "cullface": "west"}, "south": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "west"}, "west": {"uv": [1, 5, 4, 12], "texture": "#3", "cullface": "west"}, "down": {"uv": [4, 9, 5, 12], "texture": "#3"} @@ -187,21 +191,8 @@ "east": {"uv": [0, 12, 16, 16], "texture": "#3", "cullface": "east"}, "south": {"uv": [0, 12, 16, 16], "texture": "#3", "cullface": "south"}, "west": {"uv": [0, 12, 16, 16], "texture": "#3", "cullface": "west"}, - "up": {"uv": [0, 0, 16, 16], "texture": "#0"}, - "down": {"uv": [0, 0, 16, 16], "texture": "#1", "cullface": "down"} - } - }, - { - "name": "fluid", - "from": [1, 4, 1], - "to": [15, 16, 15], - "faces": { - "north": {"uv": [0, 0, 7, 6], "texture": "#5"}, - "east": {"uv": [0, 0, 7, 6], "texture": "#5"}, - "south": {"uv": [0, 0, 7, 6], "texture": "#5"}, - "west": {"uv": [0, 0, 7, 6], "texture": "#5"}, - "up": {"uv": [0, 0, 14, 14], "texture": "#4"}, - "down": {"uv": [0, 0, 7, 7], "texture": "#4"} + "up": {"uv": [0, 0, 16, 16], "texture": "#3"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#3", "cullface": "down"} } } ], diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_middle.json b/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_middle.json index 639116c..da9f55d 100644 --- a/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_middle.json +++ b/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_middle.json @@ -1,10 +1,10 @@ { + "render_type": "cutout_mipped", + "format_version": "1.21.11", "credit": "Made with Blockbench", "parent": "block/block", "textures": { "0": "createnuclear:block/reactor/frame/window", - "1": "createnuclear:fluid/uranium_flow", - "2": "createnuclear:fluid/uranium_still", "3": "createnuclear:block/reactor/casing/reactor_casing", "particle": "createnuclear:block/reactor/frame/window" }, @@ -52,22 +52,22 @@ "name": "SideRight", "from": [1, 0, 0], "to": [4, 16, 1], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, -23]}, + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 0.5]}, "faces": { "north": {"uv": [12, 5, 15, 11], "texture": "#3", "cullface": "north"}, "east": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "north"}, - "south": {"uv": [1, 0, 4, 16], "texture": "#3", "cullface": "north"} + "south": {"uv": [1, 3, 4, 13], "texture": "#3", "cullface": "north"} } }, { "name": "SideLeft", "from": [12, 0, 0], "to": [15, 16, 1], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, -23]}, + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 0.5]}, "faces": { "north": {"uv": [1, 5, 4, 11], "texture": "#3", "cullface": "north"}, "east": {"uv": [11, 0, 12, 16], "texture": "#3"}, - "south": {"uv": [12, 0, 16, 16], "texture": "#3", "cullface": "north"}, + "south": {"uv": [12, 3, 16, 13], "texture": "#3", "cullface": "north"}, "west": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "north"} } }, @@ -84,21 +84,23 @@ "name": "SideRight", "from": [15, 0, 1], "to": [16, 16, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [15.5, 8, 8]}, "faces": { "east": {"uv": [12, 5, 15, 11], "texture": "#3", "cullface": "east"}, "south": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "east"}, - "west": {"uv": [1, 0, 4, 16], "texture": "#3", "cullface": "east"} + "west": {"uv": [1, 3, 4, 13], "texture": "#3", "cullface": "east"} } }, { "name": "SideLeft", "from": [15, 0, 12], "to": [16, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [15.5, 8, 8]}, "faces": { "north": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "east"}, "east": {"uv": [1, 5, 4, 11], "texture": "#3", "cullface": "east"}, "south": {"uv": [11, 0, 12, 16], "texture": "#3"}, - "west": {"uv": [12, 0, 15, 16], "texture": "#3", "cullface": "east"} + "west": {"uv": [12, 3, 15, 13], "texture": "#3", "cullface": "east"} } }, { @@ -113,8 +115,9 @@ "name": "SideRight", "from": [12, 0, 15], "to": [15, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 15.5]}, "faces": { - "north": {"uv": [1, 0, 4, 16], "texture": "#3", "cullface": "south"}, + "north": {"uv": [1, 3, 4, 13], "texture": "#3", "cullface": "south"}, "east": {"uv": [4, 0, 5, 16], "texture": "#3"}, "south": {"uv": [12, 5, 15, 11], "texture": "#3", "cullface": "south"}, "west": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "south"} @@ -124,8 +127,9 @@ "name": "SideLeft", "from": [1, 0, 15], "to": [4, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 15.5]}, "faces": { - "north": {"uv": [12, 0, 15, 16], "texture": "#3", "cullface": "south"}, + "north": {"uv": [12, 3, 15, 13], "texture": "#3", "cullface": "south"}, "east": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "south"}, "south": {"uv": [1, 5, 4, 11], "texture": "#3", "cullface": "south"}, "west": {"uv": [4, 0, 5, 16], "texture": "#3"} @@ -143,9 +147,10 @@ "name": "SideRight", "from": [0, 0, 12], "to": [1, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [0.5, 8, 8]}, "faces": { "north": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "west"}, - "east": {"uv": [1, 0, 4, 16], "texture": "#3", "cullface": "west"}, + "east": {"uv": [1, 3, 4, 13], "texture": "#3", "cullface": "west"}, "west": {"uv": [12, 5, 15, 11], "texture": "#3", "cullface": "west"} } }, @@ -153,8 +158,9 @@ "name": "SideLeft", "from": [0, 0, 1], "to": [1, 16, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [0.5, 8, 8]}, "faces": { - "east": {"uv": [12, 0, 15, 16], "texture": "#3", "cullface": "west"}, + "east": {"uv": [12, 3, 15, 13], "texture": "#3", "cullface": "west"}, "south": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "west"}, "west": {"uv": [1, 5, 4, 11], "texture": "#3", "cullface": "west"} } @@ -166,19 +172,6 @@ "north": {"uv": [15, 5, 16, 11], "texture": "#3"}, "west": {"uv": [0, 5, 1, 11], "texture": "#3"} } - }, - { - "name": "Liquid", - "from": [1, 0, 1], - "to": [15, 16, 15], - "faces": { - "north": {"uv": [0, 0, 7, 8], "texture": "#1"}, - "east": {"uv": [0, 0, 7, 8], "texture": "#1"}, - "south": {"uv": [0, 0, 7, 8], "texture": "#1"}, - "west": {"uv": [0, 0, 7, 8], "texture": "#1"}, - "up": {"uv": [0, 0, 14, 14], "texture": "#2"}, - "down": {"uv": [0, 0, 14, 14], "texture": "#2"} - } } ], "groups": [ diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_none.json b/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_none.json index 8fa0e68..5b2688e 100644 --- a/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_none.json +++ b/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_none.json @@ -1,14 +1,13 @@ { + "render_type": "cutout_mipped", "credit": "Made with Blockbench", "parent": "block/block", "textures": { - "4": "createnuclear:fluid/uranium_still", - "5": "createnuclear:fluid/uranium_flow", "6": "createnuclear:block/reactor/casing/reactor_casing", - "8": "createnuclear:block/reactor/casing/casing_inner", - "9": "createnuclear:block/reactor/casing/casing_top", + "8": "createnuclear:block/reactor/casing/reactor_casing", + "9": "createnuclear:block/reactor/casing/reactor_casing", "10": "createnuclear:block/reactor/frame/window_single", - "particle": "createnuclear:fluid/uranium_still" + "particle": "createnuclear:block/reactor/casing/reactor_casing" }, "elements": [ { @@ -157,20 +156,6 @@ "up": {"uv": [0, 0, 16, 16], "texture": "#8"}, "down": {"uv": [0, 0, 16, 16], "texture": "#9", "cullface": "down"} } - }, - { - "name": "Liquid", - "from": [1, 2.9, 1], - "to": [15, 9.9, 15], - "rotation": {"angle": 0, "axis": "y", "origin": [7.5, 6.4, 8]}, - "faces": { - "north": {"uv": [0, 0, 7, 3.5], "texture": "#5"}, - "east": {"uv": [0, 0, 7, 3.5], "texture": "#5"}, - "south": {"uv": [0, 0, 7, 3.5], "texture": "#5"}, - "west": {"uv": [0, 0, 7, 3.5], "texture": "#5"}, - "up": {"uv": [0, 0, 14, 14], "texture": "#4"}, - "down": {"uv": [0, 0, 14, 14], "texture": "#4"} - } } ], "display": { diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_top.json b/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_top.json index e8d897c..92d91a1 100644 --- a/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_top.json +++ b/src/main/resources/assets/createnuclear/models/block/reactor/frame/frame_top.json @@ -1,14 +1,12 @@ { + "render_type": "cutout_mipped", + "format_version": "1.21.11", "credit": "Made with Blockbench", "parent": "block/block", "textures": { - "0": "createnuclear:block/reactor/casing/casing_inner", - "1": "createnuclear:block/reactor/casing/casing_top", "2": "createnuclear:block/reactor/frame/window", "3": "createnuclear:block/reactor/casing/reactor_casing", - "4": "createnuclear:fluid/uranium_flow", - "5": "createnuclear:fluid/uranium_still", - "particle": "createnuclear:block/reactor/casing/casing_inner" + "particle": "createnuclear:block/reactor/casing/reactor_casing" }, "elements": [ { @@ -56,7 +54,7 @@ "faces": { "north": {"uv": [12, 4, 15, 11], "texture": "#3", "cullface": "north"}, "east": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "north"}, - "south": {"uv": [1, 4, 4, 16], "texture": "#3", "cullface": "north"} + "south": {"uv": [1, 1, 4, 13], "texture": "#3", "cullface": "north"} } }, { @@ -66,7 +64,7 @@ "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, -23]}, "faces": { "north": {"uv": [1, 4, 4, 11], "texture": "#3", "cullface": "north"}, - "south": {"uv": [12, 4, 15, 16], "texture": "#3", "cullface": "north"}, + "south": {"uv": [12, 1, 15, 13], "texture": "#3", "cullface": "north"}, "west": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "north"} } }, @@ -85,7 +83,7 @@ "faces": { "east": {"uv": [12, 4, 15, 11], "texture": "#3", "cullface": "east"}, "south": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "east"}, - "west": {"uv": [1, 4, 4, 16], "texture": "#3", "cullface": "east"} + "west": {"uv": [1, 1, 4, 13], "texture": "#3", "cullface": "east"} } }, { @@ -95,7 +93,7 @@ "faces": { "north": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "east"}, "east": {"uv": [1, 4, 4, 11], "texture": "#3", "cullface": "east"}, - "west": {"uv": [12, 4, 15, 16], "texture": "#3", "cullface": "east"} + "west": {"uv": [12, 1, 15, 13], "texture": "#3", "cullface": "east"} } }, { @@ -111,7 +109,7 @@ "from": [12, 0, 15], "to": [15, 12, 16], "faces": { - "north": {"uv": [1, 4, 4, 16], "texture": "#3", "cullface": "south"}, + "north": {"uv": [1, 1, 4, 13], "texture": "#3", "cullface": "south"}, "south": {"uv": [12, 4, 15, 11], "texture": "#3", "cullface": "south"}, "west": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "south"} } @@ -121,7 +119,7 @@ "from": [1, 0, 15], "to": [4, 12, 16], "faces": { - "north": {"uv": [12, 4, 15, 16], "texture": "#3", "cullface": "south"}, + "north": {"uv": [12, 1, 15, 13], "texture": "#3", "cullface": "south"}, "east": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "south"}, "south": {"uv": [1, 4, 4, 11], "texture": "#3", "cullface": "south"} } @@ -141,7 +139,7 @@ "to": [1, 12, 15], "faces": { "north": {"uv": [11, 4, 12, 12], "texture": "#3", "cullface": "west"}, - "east": {"uv": [1, 4, 4, 16], "texture": "#3", "cullface": "west"}, + "east": {"uv": [1, 1, 4, 13], "texture": "#3", "cullface": "west"}, "west": {"uv": [12, 4, 15, 11], "texture": "#3", "cullface": "west"} } }, @@ -150,7 +148,7 @@ "from": [0, 0, 1], "to": [1, 12, 4], "faces": { - "east": {"uv": [12, 4, 15, 16], "texture": "#3", "cullface": "west"}, + "east": {"uv": [12, 1, 15, 13], "texture": "#3", "cullface": "west"}, "south": {"uv": [4, 4, 5, 12], "texture": "#3", "cullface": "west"}, "west": {"uv": [1, 4, 4, 11], "texture": "#3", "cullface": "west"} } @@ -167,27 +165,14 @@ "name": "Top", "from": [0, 12, 0], "to": [16, 16, 16], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, -23]}, + "rotation": {"angle": 0, "axis": "y", "origin": [8, 14, 8]}, "faces": { "north": {"uv": [0, 0, 16, 4], "texture": "#3", "cullface": "north"}, "east": {"uv": [0, 0, 16, 4], "texture": "#3", "cullface": "east"}, "south": {"uv": [0, 0, 16, 4], "texture": "#3", "cullface": "south"}, "west": {"uv": [0, 0, 16, 4], "texture": "#3", "cullface": "west"}, - "up": {"uv": [0, 0, 16, 16], "texture": "#1", "cullface": "up"}, - "down": {"uv": [0, 0, 16, 16], "texture": "#0"} - } - }, - { - "name": "fluid", - "from": [1, 0, 1], - "to": [15, 9, 15], - "faces": { - "north": {"uv": [0, 0, 7, 4.5], "texture": "#4"}, - "east": {"uv": [0, 0, 7, 4.5], "texture": "#4"}, - "south": {"uv": [0, 0, 7, 4.5], "texture": "#4"}, - "west": {"uv": [0, 0, 7, 4.5], "texture": "#4"}, - "up": {"uv": [0, 0, 14, 14], "texture": "#5"}, - "down": {"uv": [0, 0, 14, 14], "texture": "#5"} + "up": {"uv": [0, 0, 16, 16], "texture": "#3", "cullface": "up"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#3"} } } ], diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/input/block.json b/src/main/resources/assets/createnuclear/models/block/reactor/input/block.json deleted file mode 100644 index ba6c0e1..0000000 --- a/src/main/resources/assets/createnuclear/models/block/reactor/input/block.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "credit": "Made with Blockbench", - "parent": "block/block", - "textures": { - "0": "createnuclear:block/reactor/casing/reactor_casing", - "1": "createnuclear:block/reactor/input/input", - "2": "createnuclear:block/reactor/casing/casing_top", - "particle": "createnuclear:block/reactor/casing/reactor_casing" - }, - "elements": [ - { - "name": "right", - "from": [14, 0, 15], - "to": [16, 16, 16], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, - "faces": { - "east": {"uv": [0, 0, 1, 16], "texture": "#0"}, - "south": {"uv": [14, 0, 16, 16], "texture": "#1"}, - "west": {"uv": [13, 0, 14, 16], "texture": "#1"}, - "up": {"uv": [14, 0, 16, 1], "rotation": 180, "texture": "#2"}, - "down": {"uv": [14, 15, 16, 16], "rotation": 180, "texture": "#2"} - } - }, - { - "name": "left", - "from": [0, 0, 15], - "to": [2, 16, 16], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, - "faces": { - "north": {"uv": [0, 0, 2, 16], "texture": "#1"}, - "east": {"uv": [2, 0, 3, 16], "texture": "#1"}, - "south": {"uv": [0, 0, 2, 16], "texture": "#1"}, - "west": {"uv": [15, 0, 16, 16], "texture": "#0"}, - "up": {"uv": [0, 0, 2, 1], "rotation": 180, "texture": "#2"}, - "down": {"uv": [0, 15, 2, 16], "rotation": 180, "texture": "#2"} - } - }, - { - "name": "down", - "from": [2, 0, 15], - "to": [14, 2, 16], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, - "faces": { - "south": {"uv": [2, 14, 14, 16], "texture": "#1"}, - "up": {"uv": [2, 14, 14, 15], "rotation": 180, "texture": "#1"}, - "down": {"uv": [2, 15, 14, 16], "rotation": 180, "texture": "#2"} - } - }, - { - "name": "up", - "from": [2, 14, 15], - "to": [14, 16, 16], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, - "faces": { - "south": {"uv": [2, 0, 14, 2], "texture": "#1"}, - "up": {"uv": [2, 0, 14, 1], "rotation": 180, "texture": "#2"}, - "down": {"uv": [2, 1, 14, 2], "rotation": 180, "texture": "#1"} - } - }, - { - "name": "core", - "from": [0, 0, 0], - "to": [16, 16, 15], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, - "faces": { - "north": {"uv": [0, 0, 16, 16], "texture": "#0"}, - "east": {"uv": [1, 0, 16, 16], "texture": "#0"}, - "south": {"uv": [0, 0, 16, 16], "texture": "#1"}, - "west": {"uv": [0, 0, 15, 16], "texture": "#0"}, - "up": {"uv": [0, 1, 16, 16], "rotation": 180, "texture": "#2"}, - "down": {"uv": [0, 0, 16, 15], "rotation": 180, "texture": "#2"} - } - } - ], - "groups": [ - { - "name": "block", - "origin": [8, 8, 8], - "color": 0, - "children": [ - { - "name": "north", - "origin": [8, 8, 8], - "color": 0, - "children": [0, 1, 2, 3] - }, - 4 - ] - } - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/input/item.json b/src/main/resources/assets/createnuclear/models/block/reactor/input/item.json deleted file mode 100644 index 7cb6aab..0000000 --- a/src/main/resources/assets/createnuclear/models/block/reactor/input/item.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "credit": "Made with Blockbench", - "parent": "block/block", - "textures": { - "0": "createnuclear:block/reactor/casing/reactor_casing", - "1": "createnuclear:block/reactor/input/input", - "2": "createnuclear:block/reactor/casing/casing_top", - "particle": "createnuclear:block/reactor/casing/reactor_casing" - }, - "elements": [ - { - "name": "right", - "from": [0, 0, 0], - "to": [2, 16, 1], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, - "faces": { - "north": {"uv": [14, 0, 16, 16], "texture": "#1"}, - "east": {"uv": [13, 0, 14, 16], "texture": "#1"}, - "west": {"uv": [0, 0, 1, 16], "texture": "#0"}, - "up": {"uv": [14, 0, 16, 1], "texture": "#2"}, - "down": {"uv": [14, 15, 16, 16], "texture": "#2"} - } - }, - { - "name": "left", - "from": [14, 0, 0], - "to": [16, 16, 1], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, - "faces": { - "north": {"uv": [0, 0, 2, 16], "texture": "#1"}, - "east": {"uv": [15, 0, 16, 16], "texture": "#0"}, - "south": {"uv": [0, 0, 2, 16], "texture": "#1"}, - "west": {"uv": [2, 0, 3, 16], "texture": "#1"}, - "up": {"uv": [0, 0, 2, 1], "texture": "#2"}, - "down": {"uv": [0, 15, 2, 16], "texture": "#2"} - } - }, - { - "name": "down", - "from": [2, 0, 0], - "to": [14, 2, 1], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, - "faces": { - "north": {"uv": [2, 14, 14, 16], "texture": "#1"}, - "up": {"uv": [2, 14, 14, 15], "texture": "#1"}, - "down": {"uv": [2, 15, 14, 16], "texture": "#2"} - } - }, - { - "name": "up", - "from": [2, 14, 0], - "to": [14, 16, 1], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, - "faces": { - "north": {"uv": [2, 0, 14, 2], "texture": "#1"}, - "up": {"uv": [2, 0, 14, 1], "texture": "#2"}, - "down": {"uv": [2, 1, 14, 2], "texture": "#1"} - } - }, - { - "name": "core", - "from": [0, 0, 1], - "to": [16, 16, 16], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, - "faces": { - "north": {"uv": [0, 0, 16, 16], "texture": "#1"}, - "east": {"uv": [0, 0, 15, 16], "texture": "#0"}, - "south": {"uv": [0, 0, 16, 16], "texture": "#0"}, - "west": {"uv": [1, 0, 16, 16], "texture": "#0"}, - "up": {"uv": [0, 1, 16, 16], "texture": "#2"}, - "down": {"uv": [0, 0, 16, 15], "texture": "#2"} - } - } - ], - "groups": [ - { - "name": "block", - "origin": [8, 8, 8], - "color": 0, - "children": [ - { - "name": "north", - "origin": [8, 8, 8], - "color": 0, - "children": [0, 1, 2, 3] - }, - 4 - ] - } - ] -} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/output/item.json b/src/main/resources/assets/createnuclear/models/block/reactor/output/item.json index 3b55684..e6357ae 100644 --- a/src/main/resources/assets/createnuclear/models/block/reactor/output/item.json +++ b/src/main/resources/assets/createnuclear/models/block/reactor/output/item.json @@ -3,7 +3,7 @@ "parent": "block/block", "textures": { "0": "createnuclear:block/reactor/output/output", - "1": "createnuclear:block/reactor/casing/casing_top", + "1": "createnuclear:block/reactor/casing/reactor_casing", "2": "createnuclear:block/reactor/casing/reactor_casing", "1_1": "create:block/axis_top", "1_0": "create:block/axis" diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/output/output.json b/src/main/resources/assets/createnuclear/models/block/reactor/output/output.json index afeb503..76cd34b 100644 --- a/src/main/resources/assets/createnuclear/models/block/reactor/output/output.json +++ b/src/main/resources/assets/createnuclear/models/block/reactor/output/output.json @@ -3,7 +3,7 @@ "parent": "block/block", "textures": { "0": "createnuclear:block/reactor/output/output", - "1": "createnuclear:block/reactor/casing/casing_top", + "1": "createnuclear:block/reactor/casing/reactor_casing", "2": "createnuclear:block/reactor/casing/reactor_casing", "particle": "createnuclear:block/reactor/output/output" }, diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/output/output_vertical.json b/src/main/resources/assets/createnuclear/models/block/reactor/output/output_vertical.json index 03ad747..8cf59b3 100644 --- a/src/main/resources/assets/createnuclear/models/block/reactor/output/output_vertical.json +++ b/src/main/resources/assets/createnuclear/models/block/reactor/output/output_vertical.json @@ -3,7 +3,7 @@ "parent": "block/block", "textures": { "0": "createnuclear:block/reactor/output/output", - "1": "createnuclear:block/reactor/casing/casing_top", + "1": "createnuclear:block/reactor/casing/reactor_casing", "2": "createnuclear:block/reactor/casing/reactor_casing", "particle": "createnuclear:block/reactor/output/output" }, diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/rod_input/item.json b/src/main/resources/assets/createnuclear/models/block/reactor/rod_input/item.json new file mode 100644 index 0000000..3461cca --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/block/reactor/rod_input/item.json @@ -0,0 +1,92 @@ +{ + "render_type": "cutout_mipped", + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "createnuclear:block/reactor/casing/reactor_casing", + "1": "createnuclear:block/reactor/rod_input/rod_input", + "2": "createnuclear:block/reactor/casing/reactor_casing", + "particle": "createnuclear:block/reactor/casing/reactor_casing" + }, + "elements": [ + { + "name": "right", + "from": [0, 0, 0], + "to": [2, 16, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, + "faces": { + "north": {"uv": [14, 0, 16, 16], "texture": "#1"}, + "east": {"uv": [13, 0, 14, 16], "texture": "#1"}, + "west": {"uv": [0, 0, 1, 16], "texture": "#0"}, + "up": {"uv": [14, 0, 16, 1], "texture": "#2"}, + "down": {"uv": [14, 15, 16, 16], "texture": "#2"} + } + }, + { + "name": "left", + "from": [14, 0, 0], + "to": [16, 16, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, + "faces": { + "north": {"uv": [0, 0, 2, 16], "texture": "#1"}, + "east": {"uv": [15, 0, 16, 16], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 16], "texture": "#1"}, + "west": {"uv": [2, 0, 3, 16], "texture": "#1"}, + "up": {"uv": [0, 0, 2, 1], "texture": "#2"}, + "down": {"uv": [0, 15, 2, 16], "texture": "#2"} + } + }, + { + "name": "down", + "from": [2, 0, 0], + "to": [14, 2, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, + "faces": { + "north": {"uv": [2, 14, 14, 16], "texture": "#1"}, + "up": {"uv": [2, 14, 14, 15], "texture": "#1"}, + "down": {"uv": [2, 15, 14, 16], "texture": "#2"} + } + }, + { + "name": "up", + "from": [2, 14, 0], + "to": [14, 16, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, + "faces": { + "north": {"uv": [2, 0, 14, 2], "texture": "#1"}, + "up": {"uv": [2, 0, 14, 1], "texture": "#2"}, + "down": {"uv": [2, 1, 14, 2], "texture": "#1"} + } + }, + { + "name": "core", + "from": [0, 0, 1], + "to": [16, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 4.5]}, + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "east": {"uv": [0, 0, 15, 16], "texture": "#0"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#0"}, + "west": {"uv": [1, 0, 16, 16], "texture": "#0"}, + "up": {"uv": [0, 1, 16, 16], "texture": "#2"}, + "down": {"uv": [0, 0, 16, 15], "texture": "#2"} + } + } + ], + "groups": [ + { + "name": "block", + "origin": [8, 8, 8], + "color": 0, + "children": [ + { + "name": "north", + "origin": [8, 8, 8], + "color": 0, + "children": [0, 1, 2, 3] + }, + 4 + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/rod_input/rod_input.json b/src/main/resources/assets/createnuclear/models/block/reactor/rod_input/rod_input.json new file mode 100644 index 0000000..1e10b50 --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/block/reactor/rod_input/rod_input.json @@ -0,0 +1,92 @@ +{ + "render_type": "cutout_mipped", + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "createnuclear:block/reactor/casing/reactor_casing", + "1": "createnuclear:block/reactor/rod_input/rod_input", + "2": "createnuclear:block/reactor/casing/reactor_casing", + "particle": "createnuclear:block/reactor/casing/reactor_casing" + }, + "elements": [ + { + "name": "right", + "from": [14, 0, 15], + "to": [16, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, + "faces": { + "east": {"uv": [0, 0, 1, 16], "texture": "#0"}, + "south": {"uv": [14, 0, 16, 16], "texture": "#1"}, + "west": {"uv": [13, 0, 14, 16], "texture": "#1"}, + "up": {"uv": [14, 0, 16, 1], "rotation": 180, "texture": "#2"}, + "down": {"uv": [14, 15, 16, 16], "rotation": 180, "texture": "#2"} + } + }, + { + "name": "left", + "from": [0, 0, 15], + "to": [2, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, + "faces": { + "north": {"uv": [0, 0, 2, 16], "texture": "#1"}, + "east": {"uv": [2, 0, 3, 16], "texture": "#1"}, + "south": {"uv": [0, 0, 2, 16], "texture": "#1"}, + "west": {"uv": [15, 0, 16, 16], "texture": "#0"}, + "up": {"uv": [0, 0, 2, 1], "rotation": 180, "texture": "#2"}, + "down": {"uv": [0, 15, 2, 16], "rotation": 180, "texture": "#2"} + } + }, + { + "name": "down", + "from": [2, 0, 15], + "to": [14, 2, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, + "faces": { + "south": {"uv": [2, 14, 14, 16], "texture": "#1"}, + "up": {"uv": [2, 14, 14, 15], "rotation": 180, "texture": "#1"}, + "down": {"uv": [2, 15, 14, 16], "rotation": 180, "texture": "#2"} + } + }, + { + "name": "up", + "from": [2, 14, 15], + "to": [14, 16, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, + "faces": { + "south": {"uv": [2, 0, 14, 2], "texture": "#1"}, + "up": {"uv": [2, 0, 14, 1], "rotation": 180, "texture": "#2"}, + "down": {"uv": [2, 1, 14, 2], "rotation": 180, "texture": "#1"} + } + }, + { + "name": "core", + "from": [0, 0, 0], + "to": [16, 16, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11.5]}, + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#0"}, + "east": {"uv": [1, 0, 16, 16], "texture": "#0"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "west": {"uv": [0, 0, 15, 16], "texture": "#0"}, + "up": {"uv": [0, 1, 16, 16], "rotation": 180, "texture": "#2"}, + "down": {"uv": [0, 0, 16, 15], "rotation": 180, "texture": "#2"} + } + } + ], + "groups": [ + { + "name": "block", + "origin": [8, 8, 8], + "color": 0, + "children": [ + { + "name": "north", + "origin": [8, 8, 8], + "color": 0, + "children": [0, 1, 2, 3] + }, + 4 + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/block/reactor/rod_input/rod_input_vertical.json b/src/main/resources/assets/createnuclear/models/block/reactor/rod_input/rod_input_vertical.json new file mode 100644 index 0000000..3cef5f2 --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/block/reactor/rod_input/rod_input_vertical.json @@ -0,0 +1,250 @@ +{ + "render_type": "cutout_mipped", + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "createnuclear:block/reactor/rod_input/rod_input", + "1": "createnuclear:block/reactor/casing/reactor_casing", + "2": "createnuclear:block/reactor/casing/reactor_casing", + "particle": "createnuclear:block/reactor/rod_input/rod_input" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 14, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [2, 0, 16, 16], "rotation": 90, "texture": "#1"}, + "east": {"uv": [0, 0, 14, 16], "rotation": 270, "texture": "#2"}, + "south": {"uv": [2, 0, 16, 16], "rotation": 90, "texture": "#1"}, + "west": {"uv": [2, 0, 16, 16], "rotation": 90, "texture": "#2"}, + "up": {"uv": [0, 0, 16, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#2"} + } + }, + { + "from": [12, 14, 0], + "to": [16, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 12, 2, 16], "rotation": 90, "texture": "#1"}, + "east": {"uv": [14, 0, 16, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 0, 2, 4], "rotation": 90, "texture": "#1"}, + "west": {"uv": [3, 0, 5, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [0, 0, 4, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [12, 0, 16, 16], "texture": "#0"} + } + }, + { + "from": [0, 14, 0], + "to": [4, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 0, 2, 4], "rotation": 90, "texture": "#1"}, + "east": {"uv": [11, 0, 13, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 12, 2, 16], "rotation": 90, "texture": "#1"}, + "west": {"uv": [0, 0, 2, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [12, 0, 16, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0, 0, 4, 16], "texture": "#0"} + } + }, + { + "from": [4, 14, 0], + "to": [5, 16, 7], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 4, 2, 5], "rotation": 90, "texture": "#1"}, + "east": {"uv": [10, 9, 12, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [4, 9, 6, 10], "rotation": 90, "texture": "#0"}, + "west": {"uv": [10, 9, 12, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [11, 9, 12, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [11, 9, 12, 16], "texture": "#0"} + } + }, + { + "from": [11, 14, 0], + "to": [12, 16, 7], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 11, 2, 12], "rotation": 90, "texture": "#1"}, + "east": {"uv": [4, 9, 6, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [4, 9, 6, 10], "rotation": 90, "texture": "#0"}, + "west": {"uv": [4, 9, 6, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [4, 9, 5, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [4, 9, 5, 16], "texture": "#0"} + } + }, + { + "from": [11, 14, 9], + "to": [12, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [4, 6, 6, 7], "rotation": 90, "texture": "#0"}, + "east": {"uv": [4, 0, 6, 7], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 11, 2, 12], "rotation": 90, "texture": "#1"}, + "west": {"uv": [4, 0, 6, 7], "rotation": 90, "texture": "#0"}, + "up": {"uv": [4, 0, 5, 7], "rotation": 180, "texture": "#0"}, + "down": {"uv": [4, 0, 5, 7], "texture": "#0"} + } + }, + { + "from": [4, 14, 9], + "to": [5, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [4, 6, 6, 7], "rotation": 90, "texture": "#0"}, + "east": {"uv": [10, 0, 12, 7], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 4, 2, 5], "rotation": 90, "texture": "#1"}, + "west": {"uv": [10, 0, 12, 7], "rotation": 90, "texture": "#0"}, + "up": {"uv": [11, 0, 12, 7], "rotation": 180, "texture": "#0"}, + "down": {"uv": [11, 0, 12, 7], "texture": "#0"} + } + }, + { + "from": [5, 14, 10], + "to": [6, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [5, 5, 7, 6], "rotation": 90, "texture": "#0"}, + "east": {"uv": [9, 0, 11, 6], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 6, 2, 7], "rotation": 90, "texture": "#1"}, + "west": {"uv": [9, 0, 11, 6], "rotation": 90, "texture": "#0"}, + "up": {"uv": [10, 0, 11, 6], "rotation": 180, "texture": "#0"}, + "down": {"uv": [10, 0, 11, 6], "texture": "#0"} + } + }, + { + "from": [10, 14, 10], + "to": [11, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [5, 5, 7, 6], "rotation": 90, "texture": "#0"}, + "east": {"uv": [5, 0, 7, 6], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 10, 2, 11], "rotation": 90, "texture": "#1"}, + "west": {"uv": [5, 0, 7, 6], "rotation": 90, "texture": "#0"}, + "up": {"uv": [5, 0, 6, 6], "rotation": 180, "texture": "#0"}, + "down": {"uv": [5, 0, 6, 6], "texture": "#0"} + } + }, + { + "from": [10, 14, 0], + "to": [11, 16, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 10, 2, 11], "rotation": 90, "texture": "#1"}, + "east": {"uv": [5, 10, 7, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [5, 10, 7, 11], "rotation": 90, "texture": "#0"}, + "west": {"uv": [5, 10, 7, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [5, 10, 6, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [5, 10, 6, 16], "texture": "#0"} + } + }, + { + "from": [9, 14, 0], + "to": [10, 16, 5], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 9, 2, 10], "rotation": 90, "texture": "#1"}, + "east": {"uv": [6, 11, 8, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [6, 11, 8, 12], "rotation": 90, "texture": "#0"}, + "west": {"uv": [6, 11, 8, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [6, 11, 7, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [6, 11, 7, 16], "texture": "#0"} + } + }, + { + "from": [6, 14, 0], + "to": [7, 16, 5], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 6, 2, 7], "rotation": 90, "texture": "#1"}, + "east": {"uv": [8, 11, 10, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [6, 11, 8, 12], "rotation": 90, "texture": "#0"}, + "west": {"uv": [8, 11, 10, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [9, 11, 10, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9, 11, 10, 16], "texture": "#0"} + } + }, + { + "from": [6, 14, 11], + "to": [7, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [6, 4, 8, 5], "rotation": 90, "texture": "#0"}, + "east": {"uv": [8, 0, 10, 5], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 7, 2, 8], "rotation": 90, "texture": "#1"}, + "west": {"uv": [8, 0, 10, 5], "rotation": 90, "texture": "#0"}, + "up": {"uv": [9, 0, 10, 5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9, 0, 10, 5], "texture": "#0"} + } + }, + { + "from": [9, 14, 11], + "to": [10, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [6, 4, 8, 5], "rotation": 90, "texture": "#0"}, + "east": {"uv": [6, 0, 8, 5], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 9, 2, 10], "rotation": 90, "texture": "#1"}, + "west": {"uv": [6, 0, 8, 5], "rotation": 90, "texture": "#0"}, + "up": {"uv": [6, 0, 7, 5], "rotation": 180, "texture": "#0"}, + "down": {"uv": [6, 0, 7, 5], "texture": "#0"} + } + }, + { + "from": [7, 14, 12], + "to": [9, 16, 16], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [3, 7, 5, 9], "rotation": 90, "texture": "#0"}, + "east": {"uv": [7, 0, 9, 4], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 7, 2, 9], "rotation": 90, "texture": "#1"}, + "west": {"uv": [7, 0, 9, 4], "rotation": 90, "texture": "#0"}, + "up": {"uv": [7, 0, 9, 4], "rotation": 180, "texture": "#0"}, + "down": {"uv": [7, 0, 9, 4], "texture": "#0"} + } + }, + { + "from": [7, 14, 0], + "to": [9, 16, 4], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 7, 2, 9], "rotation": 90, "texture": "#1"}, + "east": {"uv": [7, 12, 9, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [3, 7, 5, 9], "rotation": 90, "texture": "#0"}, + "west": {"uv": [7, 12, 9, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [7, 12, 9, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [7, 12, 9, 16], "texture": "#0"} + } + }, + { + "from": [5, 14, 0], + "to": [6, 16, 6], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 8, 5]}, + "faces": { + "north": {"uv": [0, 5, 2, 6], "rotation": 90, "texture": "#1"}, + "east": {"uv": [9, 10, 11, 16], "rotation": 270, "texture": "#0"}, + "south": {"uv": [5, 10, 7, 11], "rotation": 90, "texture": "#0"}, + "west": {"uv": [9, 10, 11, 16], "rotation": 90, "texture": "#0"}, + "up": {"uv": [10, 10, 11, 16], "rotation": 180, "texture": "#0"}, + "down": {"uv": [10, 10, 11, 16], "texture": "#0"} + } + } + ], + "groups": [ + { + "name": "group", + "origin": [0, 0, 0], + "color": 0, + "children": [ + 0, + { + "name": "face", + "origin": [8, 8, 8], + "color": 0, + "children": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_boots/item.json b/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_boots/item.json new file mode 100644 index 0000000..01ba2ab --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_boots/item.json @@ -0,0 +1,112 @@ +{ + "format_version": "1.21.11", + "credit": "Made with Blockbench", + "textures": { + "14": "createnuclear:models/armor/default_anti_radiation_suit" + }, + "elements": [ + { + "name": "power_boot", + "from": [7.45, 0.2, 6.45], + "to": [11.95, 4.7, 10.95], + "rotation": {"angle": 0, "axis": "y", "origin": [7.8633, 12.0833, 9.7667]}, + "faces": { + "north": {"uv": [11.5, 7.16667, 10.83333, 7.83333], "texture": "#14"}, + "east": {"uv": [12.16667, 7.16667, 11.5, 7.83333], "texture": "#14"}, + "south": {"uv": [12.83333, 7.16667, 12.16667, 7.83333], "texture": "#14"}, + "west": {"uv": [10.83333, 7.16667, 10.16667, 7.83333], "texture": "#14"}, + "up": {"uv": [10.83333, 7.16667, 11.5, 6.5], "texture": "#14"}, + "down": {"uv": [11.5, 6.5, 12.16667, 7.16667], "texture": "#14"} + } + }, + { + "name": "power_boot", + "from": [3.55, 0.2, 6.45], + "to": [8.05, 4.7, 10.95], + "rotation": {"angle": 0, "axis": "y", "origin": [4, 7.75, 10]}, + "faces": { + "north": {"uv": [10.83333, 7.16667, 11.5, 7.83333], "texture": "#14"}, + "east": {"uv": [10.16667, 7.16667, 10.83333, 7.83333], "texture": "#14"}, + "south": {"uv": [12.16667, 7.16667, 12.83333, 7.83333], "texture": "#14"}, + "west": {"uv": [11.5, 7.16667, 12.16667, 7.83333], "texture": "#14"}, + "up": {"uv": [11.5, 7.16667, 10.83333, 6.5], "texture": "#14"}, + "down": {"uv": [12.16667, 6.5, 11.5, 7.16667], "texture": "#14"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [95, 0, 0], + "translation": [0, 0.5, 2.75], + "scale": [0.5, 0.5, 0.5] + }, + "thirdperson_lefthand": { + "rotation": [95, 0, 0], + "translation": [0, 0.5, 2.75], + "scale": [0.5, 0.5, 0.5] + }, + "firstperson_righthand": { + "rotation": [-180, 32.75, 180], + "translation": [0, 3.5, 0], + "scale": [0.5, 0.5, 0.5] + }, + "firstperson_lefthand": { + "rotation": [-180, 32.75, 180], + "translation": [0, 3.5, 0], + "scale": [0.5, 0.5, 0.5] + }, + "ground": { + "rotation": [85.82, -0.73, 3.41], + "translation": [0, -0.75, 0], + "scale": [0.5, 0.5, 0.5] + }, + "gui": { + "rotation": [-146, 45, 180], + "scale": [0.5, 0.5, 0.5] + }, + "head": { + "translation": [0, -37.25, -4], + "scale": [0.5, 0.5, 0.5] + } + }, + "groups": [ + { + "name": "black_anti_radiation_boots", + "origin": [8, 8, 8], + "scope": 0, + "color": 0, + "children": [ + { + "name": "right_leg", + "origin": [9.67, -2.43333, 8.76667], + "scope": 0, + "color": 0, + "children": [ + { + "name": "right_boot", + "origin": [9.7, -5.3, 8.7], + "scope": 0, + "color": 0, + "children": [0] + } + ] + }, + { + "name": "left_leg", + "origin": [5.78333, -2.43333, 8.76667], + "scope": 0, + "color": 0, + "children": [ + { + "name": "left_boot", + "origin": [5.8, -5.3, 8.7], + "scope": 0, + "color": 0, + "children": [1] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_chestplate/item.json b/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_chestplate/item.json new file mode 100644 index 0000000..09ac792 --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_chestplate/item.json @@ -0,0 +1,185 @@ +{ + "format_version": "1.21.11", + "credit": "Made with Blockbench", + "textures": { + "14": "createnuclear:models/armor/default_anti_radiation_suit" + }, + "elements": [ + { + "name": "power_chestplate_inner", + "from": [3.7, 0.75, 6.2], + "to": [11.7, 12.75, 11.2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 17.75, 9]}, + "faces": { + "north": {"uv": [0.83333, 4, 2.16667, 6], "texture": "#14"}, + "east": {"uv": [0, 4, 0.83333, 6], "texture": "#14"}, + "south": {"uv": [3, 4, 4.33333, 6], "texture": "#14"}, + "west": {"uv": [2.16667, 4, 3, 6], "texture": "#14"}, + "up": {"uv": [2.16667, 4, 0.83333, 3.16667], "texture": "#14"}, + "down": {"uv": [3.5, 3.16667, 2.16667, 4], "texture": "#14"} + } + }, + { + "name": "power_chestplate_outer", + "from": [3.4, 0.75, 5.9], + "to": [12.4, 13.75, 11.9], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 17.75, 9]}, + "faces": { + "north": {"uv": [1, 1, 2.5, 3.16667], "texture": "#14"}, + "east": {"uv": [0, 1, 1, 3.16667], "texture": "#14"}, + "south": {"uv": [3.5, 1, 5, 3.16667], "texture": "#14"}, + "west": {"uv": [2.5, 1, 3.5, 3.16667], "texture": "#14"}, + "up": {"uv": [2.5, 1, 1, 0], "texture": "#14"}, + "down": {"uv": [4, 0, 2.5, 1], "texture": "#14"} + } + }, + { + "name": "power_pants_inner", + "from": [3.7, 0.75, 6.3], + "to": [11.7, 12.75, 11.3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 17.75, 9]}, + "faces": { + "north": {"uv": [0.83333, 6.83333, 2.16667, 8.83333], "texture": "#14"}, + "east": {"uv": [0, 6.83333, 0.83333, 8.83333], "texture": "#14"}, + "south": {"uv": [3, 6.83333, 4.33333, 8.83333], "texture": "#14"}, + "west": {"uv": [2.16667, 6.83333, 3, 8.83333], "texture": "#14"}, + "up": {"uv": [2.16667, 6.83333, 0.83333, 6], "texture": "#14"}, + "down": {"uv": [3.5, 6, 2.16667, 6.83333], "texture": "#14"} + } + }, + { + "name": "power_pants_outer", + "from": [3.5, 0.75, 6], + "to": [12.5, 13.75, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 17.75, 9]}, + "faces": { + "north": {"uv": [11.66667, 1, 13.16667, 3.16667], "texture": "#14"}, + "east": {"uv": [10.66667, 1, 11.66667, 3.16667], "texture": "#14"}, + "south": {"uv": [14.16667, 1, 15.66667, 3.16667], "texture": "#14"}, + "west": {"uv": [13.16667, 1, 14.16667, 3.16667], "texture": "#14"}, + "up": {"uv": [13.16667, 1, 11.66667, 0], "texture": "#14"}, + "down": {"uv": [14.66667, 0, 13.16667, 1], "texture": "#14"} + } + }, + { + "name": "power_right_arm_inner", + "from": [11.45, 0.3, 6.25], + "to": [16.35, 13.2, 11.15], + "rotation": {"angle": 0, "axis": "y", "origin": [13.9, 6.75, 8.7]}, + "faces": { + "north": {"uv": [8.83333, 6, 8.16667, 8], "texture": "#14"}, + "east": {"uv": [9.5, 6, 8.83333, 8], "texture": "#14"}, + "south": {"uv": [10.16667, 6, 9.5, 8], "texture": "#14"}, + "west": {"uv": [8.16667, 6, 7.5, 8], "texture": "#14"}, + "up": {"uv": [8.16667, 6, 8.83333, 5.33333], "texture": "#14"}, + "down": {"uv": [8.83333, 5.33333, 9.5, 6], "texture": "#14"} + } + }, + { + "name": "power_right_arm_outer", + "from": [11.35, 0.2, 6.15], + "to": [16.45, 13.3, 11.25], + "rotation": {"angle": 0, "axis": "y", "origin": [13.9, 6.75, 8.7]}, + "faces": { + "north": {"uv": [6.16667, 6, 5.5, 8], "texture": "#14"}, + "east": {"uv": [6.83333, 6, 6.16667, 8], "texture": "#14"}, + "south": {"uv": [7.5, 6, 6.83333, 8], "texture": "#14"}, + "west": {"uv": [5.5, 6, 4.83333, 8], "texture": "#14"}, + "up": {"uv": [5.5, 6, 6.16667, 5.33333], "texture": "#14"}, + "down": {"uv": [6.16667, 5.33333, 6.83333, 6], "texture": "#14"} + } + }, + { + "name": "power_left_arm_inner", + "from": [-0.7, 0.35, 6.3], + "to": [4.1, 13.15, 11.1], + "rotation": {"angle": 0, "axis": "y", "origin": [1.7, 6.75, 8.7]}, + "faces": { + "north": {"uv": [8.16667, 6, 8.83333, 8], "texture": "#14"}, + "east": {"uv": [7.5, 6, 8.16667, 8], "texture": "#14"}, + "south": {"uv": [9.5, 6, 10.16667, 8], "texture": "#14"}, + "west": {"uv": [8.83333, 6, 9.5, 8], "texture": "#14"}, + "up": {"uv": [8.83333, 6, 8.16667, 5.33333], "texture": "#14"}, + "down": {"uv": [9.5, 5.33333, 8.83333, 6], "texture": "#14"} + } + }, + { + "name": "power_left_arm_outer", + "from": [-0.8, 0.25, 6.2], + "to": [4.2, 13.25, 11.2], + "rotation": {"angle": 0, "axis": "y", "origin": [1.7, 6.75, 8.7]}, + "faces": { + "north": {"uv": [5.5, 6, 6.16667, 8], "texture": "#14"}, + "east": {"uv": [4.83333, 6, 5.5, 8], "texture": "#14"}, + "south": {"uv": [6.83333, 6, 7.5, 8], "texture": "#14"}, + "west": {"uv": [6.16667, 6, 6.83333, 8], "texture": "#14"}, + "up": {"uv": [6.16667, 6, 5.5, 5.33333], "texture": "#14"}, + "down": {"uv": [6.83333, 5.33333, 6.16667, 6], "texture": "#14"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [95.07, -88.51, 4.51], + "translation": [0.5, -2, -1.75], + "scale": [0.5, 0.5, 0.5] + }, + "thirdperson_lefthand": { + "rotation": [95.07, -88.51, 4.51], + "translation": [0.5, -2, -1.75], + "scale": [0.5, 0.5, 0.5] + }, + "firstperson_righthand": { + "scale": [0.5, 0.5, 0.5] + }, + "firstperson_lefthand": { + "scale": [0.5, 0.5, 0.5] + }, + "ground": { + "rotation": [90, 0, 0], + "translation": [0, -0.25, 0], + "scale": [0.5, 0.5, 0.5] + }, + "gui": { + "rotation": [-152.1, 49.9, 178.86], + "scale": [0.5, 0.5, 0.5] + }, + "head": { + "translation": [0, -12, -1.25] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + }, + "groups": [ + { + "name": "black_anti_radiation_chestplate", + "origin": [8, 8, 8], + "scope": 0, + "color": 0, + "children": [ + { + "name": "body", + "origin": [7.825, 18.25, 8.85], + "scope": 0, + "color": 0, + "children": [0, 1, 2, 3] + }, + { + "name": "right_arm", + "origin": [13.8, 19.5, 8.8], + "scope": 0, + "color": 0, + "children": [4, 5] + }, + { + "name": "left_arm", + "origin": [1.8, 19.5, 8.8], + "scope": 0, + "color": 0, + "children": [6, 7] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_helmet/item.json b/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_helmet/item.json new file mode 100644 index 0000000..255e21f --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_helmet/item.json @@ -0,0 +1,87 @@ +{ + "format_version": "1.21.11", + "credit": "Made with Blockbench", + "texture_size": [96, 96], + "parent": "block/block", + "textures": { + "layer0": "createnuclear:models/armor/default_anti_radiation_suit", + "particle": "createnuclear:models/armor/default_anti_radiation_suit" + }, + "elements": [ + { + "name": "power_helmet_inner", + "from": [3.8, 0.6, 4.8], + "to": [12.2, 9, 13.2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 4.65, 9]}, + "faces": { + "north": {"uv": [6.33333, 1.33333, 7.66667, 2.66667], "texture": "#layer0"}, + "east": {"uv": [5, 1.33333, 6.33333, 2.66667], "texture": "#layer0"}, + "south": {"uv": [9, 1.33333, 10.33333, 2.66667], "texture": "#layer0"}, + "west": {"uv": [7.66667, 1.33333, 9, 2.66667], "texture": "#layer0"}, + "up": {"uv": [7.66667, 1.33333, 6.33333, 0], "texture": "#layer0"}, + "down": {"uv": [9, 0, 7.66667, 1.33333], "texture": "#layer0"} + } + }, + { + "name": "power_helm_outer", + "from": [3.5, 0, 4.5], + "to": [12.5, 9, 13.5], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 4.65, 9]}, + "faces": { + "north": {"uv": [6.33333, 4, 7.66667, 5.33333], "texture": "#layer0"}, + "east": {"uv": [5, 4, 6.33333, 5.33333], "texture": "#layer0"}, + "south": {"uv": [9, 4, 10.33333, 5.33333], "texture": "#layer0"}, + "west": {"uv": [7.66667, 4, 9, 5.33333], "texture": "#layer0"}, + "up": {"uv": [7.66667, 4, 6.33333, 2.66667], "texture": "#layer0"}, + "down": {"uv": [9, 2.66667, 7.66667, 4], "texture": "#layer0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [-87, 0, 0], + "translation": [0, -2.45, 0], + "scale": [0.5, 0.5, 0.5] + }, + "thirdperson_lefthand": { + "rotation": [-87, 0, 0], + "translation": [0, -2.45, 0], + "scale": [0.5, 0.5, 0.5] + }, + "firstperson_righthand": { + "rotation": [-90, 0, 0], + "translation": [0, 4, 0], + "scale": [0.5, 0.5, 0.5] + }, + "firstperson_lefthand": { + "rotation": [-90, 0, 0], + "translation": [0, 4, 0], + "scale": [0.5, 0.5, 0.5] + }, + "ground": { + "translation": [0, 2, 0], + "scale": [0.25, 0.25, 0.25] + }, + "gui": { + "rotation": [30, 135, 0], + "scale": [0.625, 0.625, 0.625] + } + }, + "groups": [ + { + "name": "black_anti_radiation_helmet", + "origin": [8, 8, 8], + "scope": 0, + "color": 0, + "children": [ + { + "name": "head", + "origin": [8, 36, 9], + "scope": 0, + "color": 0, + "children": [0, 1] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_leggings/item.json b/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_leggings/item.json new file mode 100644 index 0000000..0108970 --- /dev/null +++ b/src/main/resources/assets/createnuclear/models/item/default_anti_radiation_leggings/item.json @@ -0,0 +1,120 @@ +{ + "format_version": "1.21.11", + "credit": "Made with Blockbench", + "textures": { + "14": "createnuclear:models/armor/default_anti_radiation_suit" + }, + "elements": [ + { + "name": "power_leg_inner", + "from": [7.71, -2, 6.9], + "to": [11.71, 10, 10.9], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 5, 9]}, + "faces": { + "north": {"uv": [6.16667, 8.66667, 5.5, 10.66667], "texture": "#14"}, + "east": {"uv": [6.83333, 8.66667, 6.16667, 10.66667], "texture": "#14"}, + "south": {"uv": [7.5, 8.66667, 6.83333, 10.66667], "texture": "#14"}, + "west": {"uv": [5.5, 8.66667, 4.83333, 10.66667], "texture": "#14"}, + "up": {"uv": [5.5, 8.66667, 6.16667, 8], "texture": "#14"}, + "down": {"uv": [6.16667, 8, 6.83333, 8.66667], "texture": "#14"} + } + }, + { + "name": "power_leg_outer", + "from": [7.35, -2.25, 6.45], + "to": [11.85, 10.25, 10.95], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 5, 9]}, + "faces": { + "north": {"uv": [8.83333, 8.66667, 8.16667, 10.66667], "texture": "#14"}, + "east": {"uv": [9.5, 8.66667, 8.83333, 10.66667], "texture": "#14"}, + "south": {"uv": [10.16667, 8.66667, 9.5, 10.66667], "texture": "#14"}, + "west": {"uv": [8.16667, 8.66667, 7.5, 10.66667], "texture": "#14"}, + "up": {"uv": [8.16667, 8.66667, 8.83333, 8], "texture": "#14"}, + "down": {"uv": [8.83333, 8, 9.5, 8.66667], "texture": "#14"} + } + }, + { + "name": "power_leg_inner", + "from": [3.75, -2, 6.9], + "to": [7.75, 10, 10.9], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 5, 9]}, + "faces": { + "north": {"uv": [5.5, 8.66667, 6.16667, 10.66667], "texture": "#14"}, + "east": {"uv": [4.83333, 8.66667, 5.5, 10.66667], "texture": "#14"}, + "south": {"uv": [6.83333, 8.66667, 7.5, 10.66667], "texture": "#14"}, + "west": {"uv": [6.16667, 8.66667, 6.83333, 10.66667], "texture": "#14"}, + "up": {"uv": [6.16667, 8.66667, 5.5, 8], "texture": "#14"}, + "down": {"uv": [6.83333, 8, 6.16667, 8.66667], "texture": "#14"} + } + }, + { + "name": "power_leg_outer", + "from": [3.55, -2.25, 6.45], + "to": [8.05, 10.25, 10.95], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 5, 9]}, + "faces": { + "north": {"uv": [8.16667, 8.66667, 8.83333, 10.66667], "texture": "#14"}, + "east": {"uv": [7.5, 8.66667, 8.16667, 10.66667], "texture": "#14"}, + "south": {"uv": [9.5, 8.66667, 10.16667, 10.66667], "texture": "#14"}, + "west": {"uv": [8.83333, 8.66667, 9.5, 10.66667], "texture": "#14"}, + "up": {"uv": [8.83333, 8.66667, 8.16667, 8], "texture": "#14"}, + "down": {"uv": [9.5, 8, 8.83333, 8.66667], "texture": "#14"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [1.5, 0, 0], + "translation": [0.25, -0.5, -1], + "scale": [0.5, 0.5, 0.5] + }, + "thirdperson_lefthand": { + "rotation": [1.5, 0, 0], + "translation": [0.25, -0.5, -1], + "scale": [0.5, 0.5, 0.5] + }, + "firstperson_righthand": { + "scale": [0.5, 0.5, 0.5] + }, + "firstperson_lefthand": { + "scale": [0.5, 0.5, 0.5] + }, + "ground": { + "rotation": [90, 0, 0] + }, + "gui": { + "rotation": [-151.96, 54.21, 174.44], + "scale": [0.5, 0.5, 0.5] + }, + "head": { + "translation": [0, -29.5, -2.5] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + }, + "groups": [ + { + "name": "black_anti_radiation_leggings", + "origin": [8, 8, 8], + "scope": 0, + "color": 0, + "children": [ + { + "name": "right_leg", + "origin": [9.67, -2.43333, 8.76667], + "scope": 0, + "color": 0, + "children": [0, 1] + }, + { + "name": "left_leg", + "origin": [5.78333, -2.43333, 8.76667], + "scope": 0, + "color": 0, + "children": [2, 3] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/particles/irradiated_particles.json b/src/main/resources/assets/createnuclear/particles/irradiated_particles.json new file mode 100644 index 0000000..4c09429 --- /dev/null +++ b/src/main/resources/assets/createnuclear/particles/irradiated_particles.json @@ -0,0 +1,5 @@ +{ + "textures": [ + "createnuclear:irradiated_particles" + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/particles/nuclear_mushroom_cloud.json b/src/main/resources/assets/createnuclear/particles/nuclear_mushroom_cloud.json new file mode 100644 index 0000000..6e3e151 --- /dev/null +++ b/src/main/resources/assets/createnuclear/particles/nuclear_mushroom_cloud.json @@ -0,0 +1,20 @@ +{ + "textures": [ + "minecraft:explosion_0", + "minecraft:explosion_1", + "minecraft:explosion_2", + "minecraft:explosion_3", + "minecraft:explosion_4", + "minecraft:explosion_5", + "minecraft:explosion_6", + "minecraft:explosion_7", + "minecraft:explosion_8", + "minecraft:explosion_9", + "minecraft:explosion_10", + "minecraft:explosion_11", + "minecraft:explosion_12", + "minecraft:explosion_13", + "minecraft:explosion_14", + "minecraft:explosion_15" + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/particles/nuclear_mushroom_cloud_explosion.json b/src/main/resources/assets/createnuclear/particles/nuclear_mushroom_cloud_explosion.json new file mode 100644 index 0000000..6e3e151 --- /dev/null +++ b/src/main/resources/assets/createnuclear/particles/nuclear_mushroom_cloud_explosion.json @@ -0,0 +1,20 @@ +{ + "textures": [ + "minecraft:explosion_0", + "minecraft:explosion_1", + "minecraft:explosion_2", + "minecraft:explosion_3", + "minecraft:explosion_4", + "minecraft:explosion_5", + "minecraft:explosion_6", + "minecraft:explosion_7", + "minecraft:explosion_8", + "minecraft:explosion_9", + "minecraft:explosion_10", + "minecraft:explosion_11", + "minecraft:explosion_12", + "minecraft:explosion_13", + "minecraft:explosion_14", + "minecraft:explosion_15" + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/particles/nuclear_mushroom_cloud_smoke.json b/src/main/resources/assets/createnuclear/particles/nuclear_mushroom_cloud_smoke.json new file mode 100644 index 0000000..2712610 --- /dev/null +++ b/src/main/resources/assets/createnuclear/particles/nuclear_mushroom_cloud_smoke.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "minecraft:generic_7", + "minecraft:generic_6", + "minecraft:generic_5", + "minecraft:generic_4", + "minecraft:generic_3", + "minecraft:generic_2", + "minecraft:generic_1", + "minecraft:generic_0" + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/ponder/reactor/reactor_t1_ponder.nbt b/src/main/resources/assets/createnuclear/ponder/reactor/reactor_t1_ponder.nbt new file mode 100644 index 0000000..44cd6ae Binary files /dev/null and b/src/main/resources/assets/createnuclear/ponder/reactor/reactor_t1_ponder.nbt differ diff --git a/src/main/resources/assets/createnuclear/ponder/reactor/reactor_t2_ponder.nbt b/src/main/resources/assets/createnuclear/ponder/reactor/reactor_t2_ponder.nbt new file mode 100644 index 0000000..d3b8229 Binary files /dev/null and b/src/main/resources/assets/createnuclear/ponder/reactor/reactor_t2_ponder.nbt differ diff --git a/src/main/resources/assets/createnuclear/ponder/reactor/reactor_t3_ponder.nbt b/src/main/resources/assets/createnuclear/ponder/reactor/reactor_t3_ponder.nbt new file mode 100644 index 0000000..9676d99 Binary files /dev/null and b/src/main/resources/assets/createnuclear/ponder/reactor/reactor_t3_ponder.nbt differ diff --git a/src/main/resources/assets/createnuclear/ponder/reactor/setup.nbt b/src/main/resources/assets/createnuclear/ponder/reactor/setup.nbt index 227cf19..5e25912 100644 Binary files a/src/main/resources/assets/createnuclear/ponder/reactor/setup.nbt and b/src/main/resources/assets/createnuclear/ponder/reactor/setup.nbt differ diff --git a/src/main/resources/assets/createnuclear/sounds/alarm/alarm.ogg b/src/main/resources/assets/createnuclear/sounds/alarm/alarm.ogg new file mode 100644 index 0000000..34b8230 Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/alarm/alarm.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/biomes/wasteland.ogg b/src/main/resources/assets/createnuclear/sounds/biomes/wasteland.ogg new file mode 100644 index 0000000..d1947d6 Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/biomes/wasteland.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/explosion/large_nuclear_explosion.ogg b/src/main/resources/assets/createnuclear/sounds/explosion/large_nuclear_explosion.ogg new file mode 100644 index 0000000..312530d Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/explosion/large_nuclear_explosion.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/explosion/main.ogg b/src/main/resources/assets/createnuclear/sounds/explosion/main.ogg new file mode 100644 index 0000000..0038654 Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/explosion/main.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/explosion/nuclear_explosion.ogg b/src/main/resources/assets/createnuclear/sounds/explosion/nuclear_explosion.ogg new file mode 100644 index 0000000..4efa58c Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/explosion/nuclear_explosion.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/explosion/nuclear_explosion_rumble.ogg b/src/main/resources/assets/createnuclear/sounds/explosion/nuclear_explosion_rumble.ogg new file mode 100644 index 0000000..835045f Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/explosion/nuclear_explosion_rumble.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/explosion/ringing.ogg b/src/main/resources/assets/createnuclear/sounds/explosion/ringing.ogg new file mode 100644 index 0000000..d6a5ce4 Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/explosion/ringing.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/explosion/rumble.ogg b/src/main/resources/assets/createnuclear/sounds/explosion/rumble.ogg new file mode 100644 index 0000000..bde039e Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/explosion/rumble.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/explosion/shockwave.ogg b/src/main/resources/assets/createnuclear/sounds/explosion/shockwave.ogg new file mode 100644 index 0000000..4703edd Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/explosion/shockwave.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/geiger/high.ogg b/src/main/resources/assets/createnuclear/sounds/geiger/high.ogg new file mode 100644 index 0000000..88ca8b7 Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/geiger/high.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/geiger/low.ogg b/src/main/resources/assets/createnuclear/sounds/geiger/low.ogg new file mode 100644 index 0000000..7140009 Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/geiger/low.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/geiger/medium.ogg b/src/main/resources/assets/createnuclear/sounds/geiger/medium.ogg new file mode 100644 index 0000000..8d6e064 Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/geiger/medium.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/reacteur/activation.ogg b/src/main/resources/assets/createnuclear/sounds/reacteur/activation.ogg new file mode 100644 index 0000000..b043866 Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/reacteur/activation.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/reacteur/assemble_deassemble/motor_assemble.ogg b/src/main/resources/assets/createnuclear/sounds/reacteur/assemble_deassemble/motor_assemble.ogg new file mode 100644 index 0000000..3d7ac04 Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/reacteur/assemble_deassemble/motor_assemble.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/reacteur/assemble_deassemble/motor_disassemble.ogg b/src/main/resources/assets/createnuclear/sounds/reacteur/assemble_deassemble/motor_disassemble.ogg new file mode 100644 index 0000000..8e1db4c Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/reacteur/assemble_deassemble/motor_disassemble.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/reacteur/running.ogg b/src/main/resources/assets/createnuclear/sounds/reacteur/running.ogg new file mode 100644 index 0000000..761f9df Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/reacteur/running.ogg differ diff --git a/src/main/resources/assets/createnuclear/sounds/reacteur/shut_off.ogg b/src/main/resources/assets/createnuclear/sounds/reacteur/shut_off.ogg new file mode 100644 index 0000000..249f1f2 Binary files /dev/null and b/src/main/resources/assets/createnuclear/sounds/reacteur/shut_off.ogg differ diff --git a/src/main/resources/assets/createnuclear/textures/block/deepslate_nitrate_ore.png b/src/main/resources/assets/createnuclear/textures/block/deepslate_nitrate_ore.png new file mode 100644 index 0000000..6027926 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/deepslate_nitrate_ore.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/deepslate_thorium_ore.png b/src/main/resources/assets/createnuclear/textures/block/deepslate_thorium_ore.png new file mode 100644 index 0000000..875565b Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/deepslate_thorium_ore.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/nitrate_ore.png b/src/main/resources/assets/createnuclear/textures/block/nitrate_ore.png new file mode 100644 index 0000000..3eda18f Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/nitrate_ore.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_basketweave.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_basketweave.png index 18b2c25..a6e2fc1 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_basketweave.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_basketweave.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_bond.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_bond.png index 6aac6f0..90d0531 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_bond.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_bond.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_indented.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_indented.png index 007c894..77f6814 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_indented.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/alternatives/autunite_cut_indented.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/brick/autunite_cut_brick.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/brick/autunite_cut_brick.png index 34a296d..630f7cd 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/brick/autunite_cut_brick.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/brick/autunite_cut_brick.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cap/autunite_cut_cap.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cap/autunite_cut_cap.png index 007c894..77f6814 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cap/autunite_cut_cap.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cap/autunite_cut_cap.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cap/autunite_cut_cap_connected.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cap/autunite_cut_cap_connected.png index 02274e1..59c887b 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cap/autunite_cut_cap_connected.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cap/autunite_cut_cap_connected.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cut/autunite_cut.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cut/autunite_cut.png index 3cfc1ae..a18e994 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cut/autunite_cut.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/cut/autunite_cut.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/layered/autunite_cut_layered.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/layered/autunite_cut_layered.png index 3f27e32..36f6613 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/layered/autunite_cut_layered.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/layered/autunite_cut_layered.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/layered/autunite_cut_layered_connected.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/layered/autunite_cut_layered_connected.png index 0f9be1b..102073b 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/layered/autunite_cut_layered_connected.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/layered/autunite_cut_layered_connected.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_0.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_0.png index 90aab08..bd3544d 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_0.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_0.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_1.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_1.png index 823d624..ce80542 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_1.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_1.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_2.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_2.png index 97597db..4598170 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_2.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_2.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_3.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_3.png index 14f577a..bb391e7 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_3.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/natural/autunite_3.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/pillar/autunite_cut_pillar.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/pillar/autunite_cut_pillar.png index d614ad1..6187054 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/pillar/autunite_cut_pillar.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/pillar/autunite_cut_pillar.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/pillar/autunite_cut_pillar_connected.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/pillar/autunite_cut_pillar_connected.png index 46b045f..56d263a 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/pillar/autunite_cut_pillar_connected.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/pillar/autunite_cut_pillar_connected.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/polished/autunite_cut_polished.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/polished/autunite_cut_polished.png index 3980d01..8504258 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/polished/autunite_cut_polished.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/polished/autunite_cut_polished.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/slab/autunite_cut_slab.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/slab/autunite_cut_slab.png index 2914c80..9c1c53d 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/slab/autunite_cut_slab.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/slab/autunite_cut_slab.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/small_brick/autunite_cut_small_brick.png b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/small_brick/autunite_cut_small_brick.png index 1964313..fa05afc 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/small_brick/autunite_cut_small_brick.png and b/src/main/resources/assets/createnuclear/textures/block/palettes/stone_types/small_brick/autunite_cut_small_brick.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/raw_thorium_block.png b/src/main/resources/assets/createnuclear/textures/block/raw_thorium_block.png new file mode 100644 index 0000000..88c8ce6 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/raw_thorium_block.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor/casing/casing_inner.png b/src/main/resources/assets/createnuclear/textures/block/reactor/casing/casing_inner.png deleted file mode 100644 index 5783d71..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/block/reactor/casing/casing_inner.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor/casing/casing_top.png b/src/main/resources/assets/createnuclear/textures/block/reactor/casing/casing_top.png deleted file mode 100644 index c4d4460..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/block/reactor/casing/casing_top.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor/casing/reactor_casing_connected.png b/src/main/resources/assets/createnuclear/textures/block/reactor/casing/reactor_casing_connected.png index 10473d8..b2d67db 100644 Binary files a/src/main/resources/assets/createnuclear/textures/block/reactor/casing/reactor_casing_connected.png and b/src/main/resources/assets/createnuclear/textures/block/reactor/casing/reactor_casing_connected.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel.png b/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel.png deleted file mode 100644 index 52c7d1b..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel_off.png b/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel_off.png new file mode 100644 index 0000000..354c206 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel_off.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel_on.png b/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel_on.png new file mode 100644 index 0000000..33a3fdc Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel_on.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel_standby.png b/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel_standby.png new file mode 100644 index 0000000..7b9c729 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/reactor/controller/controller_panel_standby.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor/fluid_input/fluid_input.png b/src/main/resources/assets/createnuclear/textures/block/reactor/fluid_input/fluid_input.png new file mode 100644 index 0000000..e041d3d Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/reactor/fluid_input/fluid_input.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor/fluid_input/input.png b/src/main/resources/assets/createnuclear/textures/block/reactor/fluid_input/input.png new file mode 100644 index 0000000..e041d3d Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/reactor/fluid_input/input.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor/input/input.png b/src/main/resources/assets/createnuclear/textures/block/reactor/rod_input/rod_input.png similarity index 100% rename from src/main/resources/assets/createnuclear/textures/block/reactor/input/input.png rename to src/main/resources/assets/createnuclear/textures/block/reactor/rod_input/rod_input.png diff --git a/src/main/resources/assets/createnuclear/textures/block/reactor_alarm.png b/src/main/resources/assets/createnuclear/textures/block/reactor_alarm.png new file mode 100644 index 0000000..b57826a Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/reactor_alarm.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/thorium_block.png b/src/main/resources/assets/createnuclear/textures/block/thorium_block.png new file mode 100644 index 0000000..35b943f Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/thorium_block.png differ diff --git a/src/main/resources/assets/createnuclear/textures/block/thorium_ore.png b/src/main/resources/assets/createnuclear/textures/block/thorium_ore.png new file mode 100644 index 0000000..0a903ef Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/block/thorium_ore.png differ diff --git a/src/main/resources/assets/createnuclear/textures/entity/irradiated_cow.png b/src/main/resources/assets/createnuclear/textures/entity/irradiated_cow.png new file mode 100644 index 0000000..cada498 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/entity/irradiated_cow.png differ diff --git a/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_flow.png b/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_flow.png new file mode 100644 index 0000000..646a785 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_flow.png differ diff --git a/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_flow.png.mcmeta b/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_flow.png.mcmeta new file mode 100644 index 0000000..f6730e3 --- /dev/null +++ b/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_flow.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 4 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_still.png b/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_still.png new file mode 100644 index 0000000..a232dff Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_still.png differ diff --git a/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_still.png.mcmeta b/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_still.png.mcmeta new file mode 100644 index 0000000..b84e69f --- /dev/null +++ b/src/main/resources/assets/createnuclear/textures/fluid/nitrogen_still.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 4 + } +} diff --git a/src/main/resources/assets/createnuclear/textures/fluid/thorium_flow.png b/src/main/resources/assets/createnuclear/textures/fluid/thorium_flow.png new file mode 100644 index 0000000..d29c920 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/fluid/thorium_flow.png differ diff --git a/src/main/resources/assets/createnuclear/textures/fluid/thorium_flow.png.mcmeta b/src/main/resources/assets/createnuclear/textures/fluid/thorium_flow.png.mcmeta new file mode 100644 index 0000000..f6730e3 --- /dev/null +++ b/src/main/resources/assets/createnuclear/textures/fluid/thorium_flow.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 4 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/textures/fluid/thorium_still.png b/src/main/resources/assets/createnuclear/textures/fluid/thorium_still.png new file mode 100644 index 0000000..6535408 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/fluid/thorium_still.png differ diff --git a/src/main/resources/assets/createnuclear/textures/fluid/thorium_still.png.mcmeta b/src/main/resources/assets/createnuclear/textures/fluid/thorium_still.png.mcmeta new file mode 100644 index 0000000..b84e69f --- /dev/null +++ b/src/main/resources/assets/createnuclear/textures/fluid/thorium_still.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 4 + } +} diff --git a/src/main/resources/assets/createnuclear/textures/gui/advancements/backgrounds/background_advancement.png b/src/main/resources/assets/createnuclear/textures/gui/advancements/backgrounds/background_advancement.png new file mode 100644 index 0000000..d869a98 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/gui/advancements/backgrounds/background_advancement.png differ diff --git a/src/main/resources/assets/createnuclear/textures/gui/icons.png b/src/main/resources/assets/createnuclear/textures/gui/icons.png new file mode 100644 index 0000000..b971365 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/gui/icons.png differ diff --git a/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_full.png b/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_full.png new file mode 100644 index 0000000..cc7463e Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_full.png differ diff --git a/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_half.png b/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_half.png new file mode 100644 index 0000000..893d9f9 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_half.png differ diff --git a/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_hardcore_full.png b/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_hardcore_full.png new file mode 100644 index 0000000..647ee4d Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_hardcore_full.png differ diff --git a/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_hardcore_half.png b/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_hardcore_half.png new file mode 100644 index 0000000..0e8c3f8 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/gui/sprites/hud/heart/radiation_hardcore_half.png differ diff --git a/src/main/resources/assets/createnuclear/textures/gui/storage-slot.png b/src/main/resources/assets/createnuclear/textures/gui/storage-slot.png index eb8699d..39a4e50 100644 Binary files a/src/main/resources/assets/createnuclear/textures/gui/storage-slot.png and b/src/main/resources/assets/createnuclear/textures/gui/storage-slot.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/anti_radiation_boots.png b/src/main/resources/assets/createnuclear/textures/item/armors/anti_radiation_boots.png deleted file mode 100644 index 5e2aafa..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/anti_radiation_boots.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/black_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/black_anti_radiation_chestplate.png deleted file mode 100644 index 2e376a1..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/black_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/blue_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/blue_anti_radiation_chestplate.png deleted file mode 100644 index fb0136a..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/blue_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/brown_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/brown_anti_radiation_chestplate.png deleted file mode 100644 index d5f3bb1..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/brown_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/cyan_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/cyan_anti_radiation_chestplate.png deleted file mode 100644 index 59af829..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/cyan_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/gray_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/gray_anti_radiation_chestplate.png deleted file mode 100644 index 7981b59..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/gray_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/green_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/green_anti_radiation_chestplate.png deleted file mode 100644 index 707258c..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/green_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/light_blue_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/light_blue_anti_radiation_chestplate.png deleted file mode 100644 index c943950..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/light_blue_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/light_gray_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/light_gray_anti_radiation_chestplate.png deleted file mode 100644 index 6f37af5..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/light_gray_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/lime_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/lime_anti_radiation_chestplate.png deleted file mode 100644 index 6f8da44..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/lime_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/magenta_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/magenta_anti_radiation_chestplate.png deleted file mode 100644 index b0bb709..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/magenta_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/orange_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/orange_anti_radiation_chestplate.png deleted file mode 100644 index b83a217..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/orange_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/pink_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/pink_anti_radiation_chestplate.png deleted file mode 100644 index c6b096c..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/pink_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/purple_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/purple_anti_radiation_chestplate.png deleted file mode 100644 index 4e21121..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/purple_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/red_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/red_anti_radiation_chestplate.png deleted file mode 100644 index 0d73ee6..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/red_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/white_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/white_anti_radiation_chestplate.png deleted file mode 100644 index 581bbbd..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/white_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/yellow_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/yellow_anti_radiation_chestplate.png deleted file mode 100644 index 8429f5d..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/chestplates/yellow_anti_radiation_chestplate.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_boots.png b/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_boots.png new file mode 100644 index 0000000..b1fa59c Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_boots.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_chestplate.png b/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_chestplate.png new file mode 100644 index 0000000..380c01e Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_chestplate.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_helmet.png new file mode 100644 index 0000000..3431a84 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_helmet.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_leggings.png new file mode 100644 index 0000000..9f56680 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/armors/default_anti_radiation_leggings.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/black_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/black_anti_radiation_helmet.png deleted file mode 100644 index 98a0676..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/black_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/blue_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/blue_anti_radiation_helmet.png deleted file mode 100644 index 5aa8e97..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/blue_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/brown_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/brown_anti_radiation_helmet.png deleted file mode 100644 index f809bf5..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/brown_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/cyan_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/cyan_anti_radiation_helmet.png deleted file mode 100644 index 0e93c48..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/cyan_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/gray_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/gray_anti_radiation_helmet.png deleted file mode 100644 index 0cbaa9e..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/gray_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/green_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/green_anti_radiation_helmet.png deleted file mode 100644 index 69cc070..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/green_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/light_blue_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/light_blue_anti_radiation_helmet.png deleted file mode 100644 index 1b9a7c1..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/light_blue_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/light_gray_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/light_gray_anti_radiation_helmet.png deleted file mode 100644 index c426809..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/light_gray_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/lime_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/lime_anti_radiation_helmet.png deleted file mode 100644 index 28333da..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/lime_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/magenta_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/magenta_anti_radiation_helmet.png deleted file mode 100644 index 79eccd8..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/magenta_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/orange_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/orange_anti_radiation_helmet.png deleted file mode 100644 index a754982..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/orange_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/pink_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/pink_anti_radiation_helmet.png deleted file mode 100644 index 26955cd..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/pink_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/purple_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/purple_anti_radiation_helmet.png deleted file mode 100644 index cb9f6ae..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/purple_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/red_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/red_anti_radiation_helmet.png deleted file mode 100644 index baadfee..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/red_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/white_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/white_anti_radiation_helmet.png deleted file mode 100644 index 9528357..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/white_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/yellow_anti_radiation_helmet.png b/src/main/resources/assets/createnuclear/textures/item/armors/helmets/yellow_anti_radiation_helmet.png deleted file mode 100644 index 518fb04..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/helmets/yellow_anti_radiation_helmet.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/black_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/black_anti_radiation_leggings.png deleted file mode 100644 index de76aae..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/black_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/blue_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/blue_anti_radiation_leggings.png deleted file mode 100644 index 92a087c..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/blue_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/brown_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/brown_anti_radiation_leggings.png deleted file mode 100644 index 4935e7a..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/brown_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/cyan_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/cyan_anti_radiation_leggings.png deleted file mode 100644 index 7aaed84..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/cyan_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/gray_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/gray_anti_radiation_leggings.png deleted file mode 100644 index 01e1a84..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/gray_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/green_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/green_anti_radiation_leggings.png deleted file mode 100644 index ab34ea4..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/green_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/light_blue_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/light_blue_anti_radiation_leggings.png deleted file mode 100644 index 5230cf8..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/light_blue_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/light_gray_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/light_gray_anti_radiation_leggings.png deleted file mode 100644 index 29edbb2..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/light_gray_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/lime_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/lime_anti_radiation_leggings.png deleted file mode 100644 index ed28ad8..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/lime_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/magenta_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/magenta_anti_radiation_leggings.png deleted file mode 100644 index e0db666..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/magenta_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/orange_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/orange_anti_radiation_leggings.png deleted file mode 100644 index 90e25f1..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/orange_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/pink_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/pink_anti_radiation_leggings.png deleted file mode 100644 index f0c7414..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/pink_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/purple_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/purple_anti_radiation_leggings.png deleted file mode 100644 index a2fa6ec..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/purple_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/red_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/red_anti_radiation_leggings.png deleted file mode 100644 index 8f4ac05..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/red_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/white_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/white_anti_radiation_leggings.png deleted file mode 100644 index 1763c81..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/white_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/yellow_anti_radiation_leggings.png b/src/main/resources/assets/createnuclear/textures/item/armors/leggings/yellow_anti_radiation_leggings.png deleted file mode 100644 index 63178c7..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/item/armors/leggings/yellow_anti_radiation_leggings.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/empty.png b/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/empty.png new file mode 100644 index 0000000..fd63d51 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/empty.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/full.png b/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/full.png new file mode 100644 index 0000000..f9298c5 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/full.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/half.png b/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/half.png new file mode 100644 index 0000000..1f22e80 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/half.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/quarter.png b/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/quarter.png new file mode 100644 index 0000000..5203618 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/quarter.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/three_quarters.png b/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/three_quarters.png new file mode 100644 index 0000000..fc46c18 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/biome_irradiation_extractor/three_quarters.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/cooled_nitrogen_concentrate.png b/src/main/resources/assets/createnuclear/textures/item/cooled_nitrogen_concentrate.png new file mode 100644 index 0000000..51e11a2 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/cooled_nitrogen_concentrate.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/graphene.png b/src/main/resources/assets/createnuclear/textures/item/graphene.png index 78a9cd7..0992167 100644 Binary files a/src/main/resources/assets/createnuclear/textures/item/graphene.png and b/src/main/resources/assets/createnuclear/textures/item/graphene.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/nitrate.png b/src/main/resources/assets/createnuclear/textures/item/nitrate.png new file mode 100644 index 0000000..bb2f958 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/nitrate.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/nitrogen_bucket.png b/src/main/resources/assets/createnuclear/textures/item/nitrogen_bucket.png new file mode 100644 index 0000000..691532b Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/nitrogen_bucket.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/nitrogen_concentrate.png b/src/main/resources/assets/createnuclear/textures/item/nitrogen_concentrate.png new file mode 100644 index 0000000..446db53 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/nitrogen_concentrate.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/raw_thorium.png b/src/main/resources/assets/createnuclear/textures/item/raw_thorium.png new file mode 100644 index 0000000..231eff2 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/raw_thorium.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/reinforced_glass_bottle.png b/src/main/resources/assets/createnuclear/textures/item/reinforced_glass_bottle.png new file mode 100644 index 0000000..2cfcd77 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/reinforced_glass_bottle.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/thorium_bucket.png b/src/main/resources/assets/createnuclear/textures/item/thorium_bucket.png new file mode 100644 index 0000000..80a9407 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/thorium_bucket.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/thorium_dust.png b/src/main/resources/assets/createnuclear/textures/item/thorium_dust.png new file mode 100644 index 0000000..799029c Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/thorium_dust.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/thorium_ingot.png b/src/main/resources/assets/createnuclear/textures/item/thorium_ingot.png new file mode 100644 index 0000000..0a430f3 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/thorium_ingot.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/thorium_nugget.png b/src/main/resources/assets/createnuclear/textures/item/thorium_nugget.png new file mode 100644 index 0000000..276e377 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/thorium_nugget.png differ diff --git a/src/main/resources/assets/createnuclear/textures/item/thorium_rod.png b/src/main/resources/assets/createnuclear/textures/item/thorium_rod.png new file mode 100644 index 0000000..ff27f25 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/item/thorium_rod.png differ diff --git a/src/main/resources/assets/createnuclear/textures/misc/bomb_flash.png b/src/main/resources/assets/createnuclear/textures/misc/bomb_flash.png new file mode 100644 index 0000000..12e3f0c Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/misc/bomb_flash.png differ diff --git a/src/main/resources/assets/createnuclear/textures/mob_effect/iodine.png b/src/main/resources/assets/createnuclear/textures/mob_effect/iodine.png new file mode 100644 index 0000000..276fa23 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/mob_effect/iodine.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/black_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/black_anti_radiation_suit.png new file mode 100644 index 0000000..6204089 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/black_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/black_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/black_anti_radiation_suit_layer_1.png deleted file mode 100644 index 6346835..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/black_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/black_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/black_anti_radiation_suit_layer_2.png deleted file mode 100644 index 86f1b18..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/black_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/blue_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/blue_anti_radiation_suit.png new file mode 100644 index 0000000..9122ba8 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/blue_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/blue_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/blue_anti_radiation_suit_layer_1.png deleted file mode 100644 index 3a5ec07..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/blue_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/blue_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/blue_anti_radiation_suit_layer_2.png deleted file mode 100644 index 34c8ec2..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/blue_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/brown_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/brown_anti_radiation_suit.png new file mode 100644 index 0000000..cd2c4e9 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/brown_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/brown_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/brown_anti_radiation_suit_layer_1.png deleted file mode 100644 index fa70b27..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/brown_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/brown_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/brown_anti_radiation_suit_layer_2.png deleted file mode 100644 index 62ee17e..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/brown_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/cyan_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/cyan_anti_radiation_suit.png new file mode 100644 index 0000000..4f3a193 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/cyan_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/cyan_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/cyan_anti_radiation_suit_layer_1.png deleted file mode 100644 index 3dc08ee..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/cyan_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/cyan_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/cyan_anti_radiation_suit_layer_2.png deleted file mode 100644 index 0217d65..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/cyan_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/default_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/default_anti_radiation_suit.png new file mode 100644 index 0000000..b8a89e1 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/default_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/gray_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/gray_anti_radiation_suit.png new file mode 100644 index 0000000..e5038e3 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/gray_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/gray_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/gray_anti_radiation_suit_layer_1.png deleted file mode 100644 index de67016..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/gray_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/gray_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/gray_anti_radiation_suit_layer_2.png deleted file mode 100644 index 869018c..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/gray_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/green_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/green_anti_radiation_suit.png new file mode 100644 index 0000000..8eb3abd Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/green_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/green_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/green_anti_radiation_suit_layer_1.png deleted file mode 100644 index 7bd7d6e..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/green_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/green_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/green_anti_radiation_suit_layer_2.png deleted file mode 100644 index 7ff7725..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/green_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/light_blue_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/light_blue_anti_radiation_suit.png new file mode 100644 index 0000000..4584c6c Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/light_blue_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/light_blue_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/light_blue_anti_radiation_suit_layer_1.png deleted file mode 100644 index 76de36b..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/light_blue_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/light_blue_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/light_blue_anti_radiation_suit_layer_2.png deleted file mode 100644 index 734f850..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/light_blue_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/light_gray_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/light_gray_anti_radiation_suit.png new file mode 100644 index 0000000..2b2c858 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/light_gray_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/light_gray_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/light_gray_anti_radiation_suit_layer_1.png deleted file mode 100644 index eb35140..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/light_gray_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/light_gray_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/light_gray_anti_radiation_suit_layer_2.png deleted file mode 100644 index 1df7534..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/light_gray_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/lime_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/lime_anti_radiation_suit.png new file mode 100644 index 0000000..376edba Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/lime_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/lime_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/lime_anti_radiation_suit_layer_1.png deleted file mode 100644 index 24dab4e..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/lime_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/lime_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/lime_anti_radiation_suit_layer_2.png deleted file mode 100644 index dfdef32..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/lime_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/magenta_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/magenta_anti_radiation_suit.png new file mode 100644 index 0000000..91c1a8c Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/magenta_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/magenta_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/magenta_anti_radiation_suit_layer_1.png deleted file mode 100644 index 980f1fc..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/magenta_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/magenta_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/magenta_anti_radiation_suit_layer_2.png deleted file mode 100644 index 5f3dc23..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/magenta_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/orange_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/orange_anti_radiation_suit.png new file mode 100644 index 0000000..c8b3d0c Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/orange_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/orange_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/orange_anti_radiation_suit_layer_1.png deleted file mode 100644 index 777bcf1..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/orange_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/orange_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/orange_anti_radiation_suit_layer_2.png deleted file mode 100644 index 4066a8c..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/orange_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/pink_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/pink_anti_radiation_suit.png new file mode 100644 index 0000000..de04539 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/pink_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/pink_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/pink_anti_radiation_suit_layer_1.png deleted file mode 100644 index 5eeba4c..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/pink_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/pink_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/pink_anti_radiation_suit_layer_2.png deleted file mode 100644 index 67051d5..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/pink_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/purple_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/purple_anti_radiation_suit.png new file mode 100644 index 0000000..d2a0244 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/purple_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/purple_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/purple_anti_radiation_suit_layer_1.png deleted file mode 100644 index 39fd597..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/purple_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/purple_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/purple_anti_radiation_suit_layer_2.png deleted file mode 100644 index a8d8dc5..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/purple_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/red_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/red_anti_radiation_suit.png new file mode 100644 index 0000000..2b0d6b8 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/red_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/red_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/red_anti_radiation_suit_layer_1.png deleted file mode 100644 index 4ac5d3a..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/red_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/red_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/red_anti_radiation_suit_layer_2.png deleted file mode 100644 index 5687e57..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/red_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/white_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/white_anti_radiation_suit.png new file mode 100644 index 0000000..741fad4 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/white_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/white_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/white_anti_radiation_suit_layer_1.png deleted file mode 100644 index 4e433f5..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/white_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/white_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/white_anti_radiation_suit_layer_2.png deleted file mode 100644 index 1bbdc3e..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/white_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/yellow_anti_radiation_suit.png b/src/main/resources/assets/createnuclear/textures/models/armor/yellow_anti_radiation_suit.png new file mode 100644 index 0000000..2caad2b Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/models/armor/yellow_anti_radiation_suit.png differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/yellow_anti_radiation_suit_layer_1.png b/src/main/resources/assets/createnuclear/textures/models/armor/yellow_anti_radiation_suit_layer_1.png deleted file mode 100644 index d13022a..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/yellow_anti_radiation_suit_layer_1.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/models/armor/yellow_anti_radiation_suit_layer_2.png b/src/main/resources/assets/createnuclear/textures/models/armor/yellow_anti_radiation_suit_layer_2.png deleted file mode 100644 index ab3b52d..0000000 Binary files a/src/main/resources/assets/createnuclear/textures/models/armor/yellow_anti_radiation_suit_layer_2.png and /dev/null differ diff --git a/src/main/resources/assets/createnuclear/textures/particle/irradiated_particles.png b/src/main/resources/assets/createnuclear/textures/particle/irradiated_particles.png new file mode 100644 index 0000000..c3e8018 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/particle/irradiated_particles.png differ diff --git a/src/main/resources/assets/createnuclear/textures/particle/nuclear_mushroom_cloud.png b/src/main/resources/assets/createnuclear/textures/particle/nuclear_mushroom_cloud.png new file mode 100644 index 0000000..2904e00 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/particle/nuclear_mushroom_cloud.png differ diff --git a/src/main/resources/assets/minecraft/atlases/blocks.json b/src/main/resources/assets/minecraft/atlases/blocks.json index 0b97649..997ebd9 100644 --- a/src/main/resources/assets/minecraft/atlases/blocks.json +++ b/src/main/resources/assets/minecraft/atlases/blocks.json @@ -1,5 +1,13 @@ { "sources": [ + { + "type": "single", + "resource": "createnuclear:fluid/thorium_flow" + }, + { + "type": "single", + "resource": "createnuclear:fluid/thorium_still" + }, { "type": "single", "resource": "createnuclear:fluid/uranium_flow" @@ -7,6 +15,19 @@ { "type": "single", "resource": "createnuclear:fluid/uranium_still" + }, + { + "type": "single", + "resource": "createnuclear:fluid/nitrogen_flow" + }, + { + "type": "single", + "resource": "createnuclear:fluid/nitrogen_still" + }, + { + "type": "directory", + "source": "models/armor", + "prefix": "models/armor/" } ] } \ No newline at end of file diff --git a/src/main/resources/createnuclear.neoforge.mixins.json b/src/main/resources/createnuclear.neoforge.mixins.json index 02224e2..95c1b01 100644 --- a/src/main/resources/createnuclear.neoforge.mixins.json +++ b/src/main/resources/createnuclear.neoforge.mixins.json @@ -5,9 +5,14 @@ "package": "net.nuclearteam.createnuclear.foundation.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ - "BaseFireBlockMixin" + "BaseFireBlockMixin", + "SmithingTransformRecipeMixin" ], "client": [ + "client.RadiationHeartMixin", + "client.AntiRadiationArmorTextureMixin", + "client.CameraAccessor", + "client.GameRendererMixin" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/resources/data/createnuclear/structure/empty_platform.nbt b/src/main/resources/data/createnuclear/structure/empty_platform.nbt new file mode 100644 index 0000000..1181be1 Binary files /dev/null and b/src/main/resources/data/createnuclear/structure/empty_platform.nbt differ diff --git a/src/main/resources/icon.png b/src/main/resources/icon.png new file mode 100644 index 0000000..41afd40 Binary files /dev/null and b/src/main/resources/icon.png differ